(TextController) Reformatted to reduce LOC
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-controller-event-handler.cpp
index c6c4058..5d78405 100644 (file)
@@ -24,6 +24,7 @@
 #include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/cursor-helper-functions.h>
 #include <dali-toolkit/internal/text/text-controller-impl.h>
 #include <dali-toolkit/internal/text/text-editable-control-interface.h>
 
@@ -80,6 +81,22 @@ void Controller::EventHandler::KeyboardFocusLostEvent(Controller& controller)
   {
     if(EventData::INTERRUPTED != controller.mImpl->mEventData->mState)
     {
+      // Init selection position
+      if(controller.mImpl->mEventData->mState == EventData::SELECTING)
+      {
+        uint32_t oldStart, oldEnd;
+        oldStart = controller.mImpl->mEventData->mLeftSelectionPosition;
+        oldEnd   = controller.mImpl->mEventData->mRightSelectionPosition;
+
+        controller.mImpl->mEventData->mLeftSelectionPosition  = controller.mImpl->mEventData->mPrimaryCursorPosition;
+        controller.mImpl->mEventData->mRightSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
+
+        if(controller.mImpl->mSelectableControlInterface != nullptr)
+        {
+          controller.mImpl->mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, controller.mImpl->mEventData->mPrimaryCursorPosition, controller.mImpl->mEventData->mPrimaryCursorPosition);
+        }
+      }
+
       controller.mImpl->ChangeState(EventData::INACTIVE);
 
       if(!controller.mImpl->IsShowingRealText())
@@ -150,12 +167,22 @@ bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyE
         // Release the active highlight.
         if(controller.mImpl->mEventData->mState == EventData::SELECTING)
         {
+          uint32_t oldStart, oldEnd;
+          oldStart = controller.mImpl->mEventData->mLeftSelectionPosition;
+          oldEnd   = controller.mImpl->mEventData->mRightSelectionPosition;
+
           controller.mImpl->ChangeState(EventData::EDITING);
 
           // Update selection position.
           controller.mImpl->mEventData->mLeftSelectionPosition  = controller.mImpl->mEventData->mPrimaryCursorPosition;
           controller.mImpl->mEventData->mRightSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
           controller.mImpl->mEventData->mUpdateCursorPosition   = true;
+
+          if(controller.mImpl->mSelectableControlInterface != nullptr)
+          {
+            controller.mImpl->mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, controller.mImpl->mEventData->mLeftSelectionPosition, controller.mImpl->mEventData->mRightSelectionPosition);
+          }
+
           controller.mImpl->RequestRelayout();
         }
         return false;
@@ -246,12 +273,36 @@ bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyE
       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::KeyEvent %p keyString %s\n", &controller, keyString.c_str());
       if(!controller.IsEditable()) return false;
 
-      if(!keyString.empty())
+      std::string refinedKey = keyString;
+      if(controller.mImpl->mInputFilter != NULL && !refinedKey.empty())
+      {
+        bool accepted = false;
+        bool rejected = false;
+        accepted      = controller.mImpl->mInputFilter->Contains(Toolkit::InputFilter::Property::ACCEPTED, keyString);
+        rejected      = controller.mImpl->mInputFilter->Contains(Toolkit::InputFilter::Property::REJECTED, keyString);
+
+        if(!accepted)
+        {
+          // The filtered key is set to empty.
+          refinedKey = "";
+          // Signal emits when the character to be inserted is filtered by the accepted filter.
+          controller.mImpl->mEditableControlInterface->InputFiltered(Toolkit::InputFilter::Property::ACCEPTED);
+        }
+        if(rejected)
+        {
+          // The filtered key is set to empty.
+          refinedKey = "";
+          // Signal emits when the character to be inserted is filtered by the rejected filter.
+          controller.mImpl->mEditableControlInterface->InputFiltered(Toolkit::InputFilter::Property::REJECTED);
+        }
+      }
+
+      if(!refinedKey.empty())
       {
         // InputMethodContext is no longer handling key-events
         controller.mImpl->ClearPreEditFlag();
 
-        controller.InsertText(keyString, COMMIT);
+        controller.InsertText(refinedKey, COMMIT);
 
         textChanged = true;
 
@@ -287,12 +338,52 @@ bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyE
      (NULL != controller.mImpl->mEditableControlInterface))
   {
     // Do this last since it provides callbacks into application code
-    controller.mImpl->mEditableControlInterface->TextChanged();
+    controller.mImpl->mEditableControlInterface->TextChanged(false);
   }
 
   return true;
 }
 
+void Controller::EventHandler::AnchorEvent(Controller& controller, float x, float y)
+{
+  if(!controller.mImpl->mMarkupProcessorEnabled ||
+     !controller.mImpl->mModel->mLogicalModel->mAnchors.Count() ||
+     !controller.mImpl->IsShowingRealText())
+  {
+    return;
+  }
+
+  CharacterIndex cursorPosition = 0u;
+
+  // Convert from control's coords to text's coords.
+  const float xPosition = x - controller.mImpl->mModel->mScrollPosition.x;
+  const float yPosition = y - controller.mImpl->mModel->mScrollPosition.y;
+
+  // Whether to touch point hits on a glyph.
+  bool matchedCharacter = false;
+  cursorPosition        = Text::GetClosestCursorIndex(controller.mImpl->mModel->mVisualModel,
+                                               controller.mImpl->mModel->mLogicalModel,
+                                               controller.mImpl->mMetrics,
+                                               xPosition,
+                                               yPosition,
+                                               CharacterHitTest::TAP,
+                                               matchedCharacter);
+
+  for(const auto& anchor : controller.mImpl->mModel->mLogicalModel->mAnchors)
+  {
+    // Anchor clicked if the calculated cursor position is within the range of anchor.
+    if(cursorPosition >= anchor.startIndex && cursorPosition < anchor.endIndex)
+    {
+      if(controller.mImpl->mAnchorControlInterface && anchor.href)
+      {
+        std::string href(anchor.href);
+        controller.mImpl->mAnchorControlInterface->AnchorClicked(href);
+        break;
+      }
+    }
+  }
+}
+
 void Controller::EventHandler::TapEvent(Controller& controller, unsigned int tapCount, float x, float y)
 {
   DALI_ASSERT_DEBUG(controller.mImpl->mEventData && "Unexpected TapEvent");
@@ -464,6 +555,27 @@ void Controller::EventHandler::SelectEvent(Controller& controller, float x, floa
   }
 }
 
+void Controller::EventHandler::SelectEvent(Controller& controller, const uint32_t start, const uint32_t end, SelectionType selectType)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::SelectEvent\n");
+
+  if(NULL != controller.mImpl->mEventData)
+  {
+    if(selectType == SelectionType::RANGE)
+    {
+      Event event(Event::SELECT_RANGE);
+      event.p2.mUint = start;
+      event.p3.mUint = end;
+      controller.mImpl->mEventData->mEventQueue.push_back(event);
+    }
+
+    controller.mImpl->mEventData->mCheckScrollAmount     = true;
+    controller.mImpl->mEventData->mIsLeftHandleSelected  = true;
+    controller.mImpl->mEventData->mIsRightHandleSelected = true;
+    controller.mImpl->RequestRelayout();
+  }
+}
+
 void Controller::EventHandler::ProcessModifyEvents(Controller& controller)
 {
   Vector<ModifyEvent>& events = controller.mImpl->mModifyEvents;
@@ -504,12 +616,21 @@ void Controller::EventHandler::ProcessModifyEvents(Controller& controller)
 
   if(NULL != controller.mImpl->mEventData)
   {
+    uint32_t oldStart, oldEnd;
+    oldStart = controller.mImpl->mEventData->mLeftSelectionPosition;
+    oldEnd   = controller.mImpl->mEventData->mRightSelectionPosition;
+
     // When the text is being modified, delay cursor blinking
     controller.mImpl->mEventData->mDecorator->DelayCursorBlink();
 
     // Update selection position after modifying the text
     controller.mImpl->mEventData->mLeftSelectionPosition  = controller.mImpl->mEventData->mPrimaryCursorPosition;
     controller.mImpl->mEventData->mRightSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
+
+    if(controller.mImpl->mSelectableControlInterface != nullptr && controller.mImpl->mEventData->mState == EventData::SELECTING)
+    {
+      controller.mImpl->mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, controller.mImpl->mEventData->mLeftSelectionPosition, controller.mImpl->mEventData->mRightSelectionPosition);
+    }
   }
 
   // DISCARD temporary text
@@ -742,7 +863,7 @@ InputMethodContext::CallbackData Controller::EventHandler::OnInputMethodContextE
      (NULL != controller.mImpl->mEditableControlInterface))
   {
     // Do this last since it provides callbacks into application code
-    controller.mImpl->mEditableControlInterface->TextChanged();
+    controller.mImpl->mEditableControlInterface->TextChanged(false);
   }
 
   return callbackData;
@@ -831,43 +952,17 @@ void Controller::EventHandler::TextPopupButtonTouched(Controller& controller, Da
   {
     case Toolkit::TextSelectionPopup::CUT:
     {
-      if(!controller.IsEditable()) return;
-      controller.mImpl->SendSelectionToClipboard(true); // Synchronous call to modify text
-      controller.mImpl->mOperationsPending = ALL_OPERATIONS;
-
-      if((0u != controller.mImpl->mModel->mLogicalModel->mText.Count()) ||
-         !controller.mImpl->IsPlaceholderAvailable())
-      {
-        controller.mImpl->QueueModifyEvent(ModifyEvent::TEXT_DELETED);
-      }
-      else
-      {
-        controller.ShowPlaceholderText();
-      }
-
-      controller.mImpl->mEventData->mUpdateCursorPosition = true;
-      controller.mImpl->mEventData->mScrollAfterDelete    = true;
-
-      controller.mImpl->RequestRelayout();
-
-      if(NULL != controller.mImpl->mEditableControlInterface)
-      {
-        controller.mImpl->mEditableControlInterface->TextChanged();
-      }
+      controller.CutText();
       break;
     }
     case Toolkit::TextSelectionPopup::COPY:
     {
-      controller.mImpl->SendSelectionToClipboard(false); // Text not modified
-
-      controller.mImpl->mEventData->mUpdateCursorPosition = true;
-
-      controller.mImpl->RequestRelayout(); // Cursor, Handles, Selection Highlight, Popup
+      controller.CopyText();
       break;
     }
     case Toolkit::TextSelectionPopup::PASTE:
     {
-      controller.mImpl->RequestGetTextFromClipboard(); // Request clipboard service to retrieve an item
+      controller.PasteText();
       break;
     }
     case Toolkit::TextSelectionPopup::SELECT: