Add Filter in InputFilter 08/285608/3
authorBowon Ryu <bowon.ryu@samsung.com>
Thu, 15 Dec 2022 06:33:30 +0000 (15:33 +0900)
committerBowon Ryu <bowon.ryu@samsung.com>
Thu, 15 Dec 2022 10:49:10 +0000 (19:49 +0900)
This patch enables filtering of strings from InsertText() by regex.

Change-Id: I1b28f0e24c782f94ee0453b1366d51ea08e45c36
Signed-off-by: Bowon Ryu <bowon.ryu@samsung.com>
automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp
dali-toolkit/internal/text/controller/text-controller-text-updater.cpp
dali-toolkit/internal/text/input-filter.cpp
dali-toolkit/internal/text/input-filter.h

index 94855ca..63eac09 100644 (file)
@@ -1788,6 +1788,57 @@ int utcDaliTextFieldPositionWithInputMethodContext(void)
   END_TEST;
 }
 
+int utcDaliTextFieldInputFilterWithInputMethodContext(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" utcDaliTextFieldInputFilterWithInputMethodContext");
+  TextField field = TextField::New();
+  DALI_TEST_CHECK(field);
+
+  Property::Map inputFilter;
+  inputFilter[InputFilter::Property::ACCEPTED] = "[\\d]";
+  inputFilter[InputFilter::Property::REJECTED] = "[5-7]";
+
+  // Set input filter to TextField.
+  field.SetProperty(DevelTextField::Property::INPUT_FILTER, inputFilter);
+
+  application.GetScene().Add(field);
+
+  // connect to the input filtered signal.
+  ConnectionTracker* testTracker = new ConnectionTracker();
+  DevelTextField::InputFilteredSignal(field).Connect(&TestInputFilteredCallback);
+  bool inputFilteredSignal = false;
+  field.ConnectSignal(testTracker, "inputFiltered", CallbackFunctor(&inputFilteredSignal));
+
+  // get InputMethodContext
+  std::string                   text;
+  InputMethodContext::EventData imfEvent;
+  InputMethodContext            inputMethodContext = DevelTextField::GetInputMethodContext(field);
+
+  field.SetKeyInputFocus();
+  field.SetProperty(DevelTextField::Property::ENABLE_EDITING, true);
+
+  // input text
+  gInputFilteredAcceptedCallbackCalled = false;
+  imfEvent = InputMethodContext::EventData(InputMethodContext::COMMIT, "Hello1234", 0, 9);
+  inputMethodContext.EventReceivedSignal().Emit(inputMethodContext, imfEvent);
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK(gInputFilteredAcceptedCallbackCalled);
+  DALI_TEST_EQUALS(field.GetProperty<std::string>(TextField::Property::TEXT), std::string("1234"), TEST_LOCATION);
+
+  inputFilteredSignal = false;
+  gInputFilteredRejectedCallbackCalled = false;
+  imfEvent = InputMethodContext::EventData(InputMethodContext::COMMIT, "1234567", 0, 7);
+  inputMethodContext.EventReceivedSignal().Emit(inputMethodContext, imfEvent);
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK(gInputFilteredRejectedCallbackCalled);
+  DALI_TEST_EQUALS(field.GetProperty<std::string>(TextField::Property::TEXT), std::string("12341234"), TEST_LOCATION);
+
+  END_TEST;
+}
+
 // Negative test for the textChanged signal.
 int utcDaliTextFieldTextChangedN(void)
 {
index de812af..144fe15 100644 (file)
@@ -221,19 +221,41 @@ void Controller::TextUpdater::InsertText(Controller& controller, const std::stri
 
   if(!text.empty())
   {
+    std::string redefinedText = text;
+
+    if(controller.mImpl->mInputFilter != NULL)
+    {
+      bool accepted = false;
+      bool rejected = false;
+
+      accepted = impl.mInputFilter->Filter(Toolkit::InputFilter::Property::ACCEPTED, redefinedText);
+      rejected = impl.mInputFilter->Filter(Toolkit::InputFilter::Property::REJECTED, redefinedText);
+
+      if(accepted)
+      {
+        // Signal emits when the string to be inserted is filtered by the accepted filter.
+        controller.mImpl->mEditableControlInterface->InputFiltered(Toolkit::InputFilter::Property::ACCEPTED);
+      }
+      if(rejected)
+      {
+        // Signal emits when the string to be inserted is filtered by the rejected filter.
+        controller.mImpl->mEditableControlInterface->InputFiltered(Toolkit::InputFilter::Property::REJECTED);
+      }
+    }
+
     //  Convert text into UTF-32
-    utf32Characters.Resize(text.size());
+    utf32Characters.Resize(redefinedText.size());
 
     // This is a bit horrible but std::string returns a (signed) char*
-    const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(text.c_str());
+    const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(redefinedText.c_str());
 
     // Transform a text array encoded in utf8 into an array encoded in utf32.
     // It returns the actual number of characters.
-    characterCount = Utf8ToUtf32(utf8, text.size(), utf32Characters.Begin());
+    characterCount = Utf8ToUtf32(utf8, redefinedText.size(), utf32Characters.Begin());
     utf32Characters.Resize(characterCount);
 
-    DALI_ASSERT_DEBUG(text.size() >= utf32Characters.Count() && "Invalid UTF32 conversion length");
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "UTF8 size %d, UTF32 size %d\n", text.size(), utf32Characters.Count());
+    DALI_ASSERT_DEBUG(redefinedText.size() >= utf32Characters.Count() && "Invalid UTF32 conversion length");
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "UTF8 size %d, UTF32 size %d\n", redefinedText.size(), utf32Characters.Count());
   }
 
   if(0u != utf32Characters.Count()) // Check if Utf8ToUtf32 conversion succeeded
index eafcfe7..4a67a0b 100644 (file)
@@ -92,6 +92,47 @@ bool InputFilter::Contains(Toolkit::InputFilter::Property::Type type, std::strin
   return match;
 }
 
+bool InputFilter::Filter(Toolkit::InputFilter::Property::Type type, std::string& text)
+{
+  std::regex pattern;
+  std::string result;
+
+  if(type == Toolkit::InputFilter::Property::ACCEPTED)
+  {
+    if(mAccepted.empty())
+    {
+      return false;
+    }
+    pattern = mAccepted;
+
+    auto start = std::sregex_iterator(text.begin(), text.end(), pattern);
+    auto end   = std::sregex_iterator();
+
+    while (start != end) {
+      result += start->str();
+      ++start;
+    }
+  }
+  else if(type == Toolkit::InputFilter::Property::REJECTED)
+  {
+    if(mRejected.empty())
+    {
+      return false;
+    }
+    pattern = mRejected;
+
+    result = std::regex_replace(text, pattern, "");
+  }
+
+  if(result.compare(text) == 0)
+  {
+    return false;
+  }
+
+  text = result;
+  return true;
+}
+
 } // namespace Text
 
 } // namespace Toolkit
index 6de0132..be1f019 100644 (file)
@@ -63,6 +63,14 @@ public: // Intended for internal use
    */
   bool Contains(Toolkit::InputFilter::Property::Type type, std::string source);
 
+  /**
+   * @brief Filtering the text using regex.
+   * @param[in] type ACCEPTED or REJECTED
+   * @param[in,out] text The string value to filter and write back.
+   * @return @e true if the text is filtered by the regex, otherwise returns @e false.
+   */
+  bool Filter(Toolkit::InputFilter::Property::Type type, std::string& text);
+
 private:
   std::string mAccepted;
   std::string mRejected;