Added TextChanged signal to TextField 01/40501/6
authorPaul Wisbey <p.wisbey@samsung.com>
Thu, 4 Jun 2015 10:57:59 +0000 (11:57 +0100)
committerPaul Wisbey <p.wisbey@samsung.com>
Thu, 4 Jun 2015 13:38:23 +0000 (14:38 +0100)
Change-Id: I7e0560b289d321db65d3a71de273b407c2f1f0f5

automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp
dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/controls/text-controls/text-field-impl.h
dali-toolkit/internal/controls/text-controls/text-label-impl.cpp
dali-toolkit/internal/controls/text-controls/text-label-impl.h
dali-toolkit/internal/text/text-control-interface.h
dali-toolkit/internal/text/text-controller-impl.h
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/public-api/controls/text-controls/text-field.cpp
dali-toolkit/public-api/controls/text-controls/text-field.h

index a8be49ebdce830ee55817f545b0c26f7568fa9ca..d19b3a12cd997aa40cad05ac6287c2a7c15ff45a 100644 (file)
@@ -55,11 +55,19 @@ const char* const PROPERTY_NAME_DECORATION_BOUNDING_BOX = "decoration-bounding-b
 const char* const PROPERTY_NAME_HORIZONTAL_ALIGNMENT    = "horizontal-alignment";
 const char* const PROPERTY_NAME_VERTICAL_ALIGNMENT      = "vertical-alignment";
 
+static bool gTextChangedCallBackCalled;
 static bool gMaxCharactersCallBackCalled;
 
+static void TestTextChangedCallback( TextField control )
+{
+  tet_infoline(" TestTextChangedCallback");
+
+  gTextChangedCallBackCalled = true;
+}
+
 static void TestMaxLengthReachedCallback( TextField control )
 {
-  tet_infoline(" TestMaxLengthReachedCallbackCallback");
+  tet_infoline(" TestMaxLengthReachedCallback");
 
   gMaxCharactersCallBackCalled = true;
 }
@@ -332,6 +340,60 @@ int utcDaliTextFieldAtlasRenderP(void)
   END_TEST;
 }
 
+// Positive test for the text-changed signal.
+int utcDaliTextFieldTextChangedP(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" utcDaliTextFieldTextChangedP");
+  TextField field = TextField::New();
+  DALI_TEST_CHECK( field );
+
+  Stage::GetCurrent().Add(field);
+
+  field.TextChangedSignal().Connect(&TestTextChangedCallback);
+
+  gTextChangedCallBackCalled = false;
+  field.SetProperty( TextField::Property::TEXT, "ABC" );
+  DALI_TEST_CHECK( gTextChangedCallBackCalled );
+
+  application.SendNotification();
+
+  field.SetKeyInputFocus();
+
+  Dali::Integration::KeyEvent keyevent;
+  keyevent.keyName = "D";
+  keyevent.keyString = "D";
+  keyevent.keyCode = 0;
+  keyevent.keyModifier = 0;
+  keyevent.time = 0;
+  keyevent.state = Integration::KeyEvent::Down;
+
+  gTextChangedCallBackCalled = false;
+  application.ProcessEvent( keyevent );
+  DALI_TEST_CHECK( gTextChangedCallBackCalled );
+
+  END_TEST;
+}
+
+// Negative test for the text-changed signal.
+int utcDaliTextFieldTextChangedN(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" utcDaliTextFieldTextChangedN");
+  TextField field = TextField::New();
+  DALI_TEST_CHECK( field );
+
+  Stage::GetCurrent().Add(field);
+
+  field.TextChangedSignal().Connect(&TestTextChangedCallback);
+
+  gTextChangedCallBackCalled = false;
+  field.SetProperty( TextField::Property::PLACEHOLDER_TEXT, "ABC" ); // Setting placeholder, not TEXT
+  DALI_TEST_CHECK( ! gTextChangedCallBackCalled );
+
+  END_TEST;
+}
+
 // Positive test for Max Characters reached signal.
 int utcDaliTextFieldMaxCharactersReachedP(void)
 {
index 11ec5c21918b82c06e8ee710aacf6f75573ce51a..753d34743f8fabc07fd1130732b65a60bc7018c7 100644 (file)
@@ -119,6 +119,7 @@ DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "selection-highlight-color",
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "decoration-bounding-box",              RECTANGLE, DECORATION_BOUNDING_BOX              )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "input-method-settings",                MAP,       INPUT_METHOD_SETTINGS                )
 
+DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "text-changed",       SIGNAL_TEXT_CHANGED )
 DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "max-length-reached", SIGNAL_MAX_LENGTH_REACHED )
 
 DALI_TYPE_REGISTRATION_END()
@@ -825,7 +826,11 @@ bool TextField::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface*
   bool connected( true );
   Toolkit::TextField field = Toolkit::TextField::DownCast( handle );
 
-  if( 0 == strcmp( signalName.c_str(), SIGNAL_MAX_LENGTH_REACHED ) )
+  if( 0 == strcmp( signalName.c_str(), SIGNAL_TEXT_CHANGED ) )
+  {
+    field.TextChangedSignal().Connect( tracker, functor );
+  }
+  else if( 0 == strcmp( signalName.c_str(), SIGNAL_MAX_LENGTH_REACHED ) )
   {
     field.MaxLengthReachedSignal().Connect( tracker, functor );
   }
@@ -838,6 +843,11 @@ bool TextField::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface*
   return connected;
 }
 
+Toolkit::TextField::TextChangedSignalType& TextField::TextChangedSignal()
+{
+  return mTextChangedSignal;
+}
+
 Toolkit::TextField::MaxLengthReachedSignalType& TextField::MaxLengthReachedSignal()
 {
   return mMaxLengthReachedSignal;
@@ -1032,6 +1042,12 @@ void TextField::RequestTextRelayout()
   RelayoutRequest();
 }
 
+void TextField::TextChanged()
+{
+  Dali::Toolkit::TextField handle( GetOwner() );
+  mTextChangedSignal.Emit( handle );
+}
+
 void TextField::MaxLengthReached()
 {
   Dali::Toolkit::TextField handle( GetOwner() );
index 5e0df24395226d6a3c8257bfe6a1f7be60659048..85b88e22ebbc04a2d421bcb76e191dc47cb4a2fb 100644 (file)
@@ -79,6 +79,11 @@ public:
    */
   static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor );
 
+  /**
+   * @copydoc TextField::TextChangedSignal()
+   */
+  Toolkit::TextField::TextChangedSignalType&  TextChangedSignal();
+
   /**
    * @copydoc TextField::MaxLengthReachedSignal()
    */
@@ -146,6 +151,11 @@ private: // From Control
    */
   virtual void RequestTextRelayout();
 
+  /**
+   * @copydoc Text::ControlInterface::TextChanged()
+   */
+  virtual void TextChanged();
+
   /**
    * @copydoc Text::ControlInterface::MaxLengthReached()
    */
@@ -193,6 +203,7 @@ private: // Implementation
 private: // Data
 
   // Signals
+  Toolkit::TextField::TextChangedSignalType mTextChangedSignal;
   Toolkit::TextField::MaxLengthReachedSignalType mMaxLengthReachedSignal;
 
   Text::ControllerPtr mController;
index 35761df04f7f962b8594bb7eea5d5f167b0f4aab..004609ff6088112875801e3ef077041dbb78644a 100644 (file)
@@ -494,6 +494,11 @@ void TextLabel::RequestTextRelayout()
   RelayoutRequest();
 }
 
+void TextLabel::TextChanged()
+{
+  // TextLabel does not provide a signal for this
+}
+
 void TextLabel::MaxLengthReached()
 {
   // Pure Virtual from TextController Interface, only needed when inputting text
index 3e0fd35605744fc43cd6cd936e26125ee2331f1d..54b30dde646454a2367c69ed92ec5c9e47030285 100644 (file)
@@ -97,6 +97,11 @@ private: // From Control
    */
   virtual void RequestTextRelayout();
 
+  /**
+   * @copydoc Text::ControlInterface::TextChanged()
+   */
+  virtual void TextChanged();
+
   /**
    * @copydoc Text::ControlInterface::MaxLengthReached()
    */
index d7ed8f49400e06ff081db00299a76e7b3c68103f..e485be976d80f86f50422852ce9cddae1f0822ac 100644 (file)
@@ -49,6 +49,11 @@ public:
    */
   virtual void RequestTextRelayout() = 0;
 
+  /**
+   * @brief Called to signal that text has been inserted or deleted.
+   */
+  virtual void TextChanged() = 0;
+
   /**
    * @brief Called when the number of characters to be inserted exceeds the maximum limit
    */
index 3020e67d153083c0a804f758767ffbd5ce60dd9a..ab2764caf32a7ddf196e72b2a886497b0fdd8e36 100644 (file)
@@ -231,6 +231,12 @@ struct Controller::Impl
    */
   void QueueModifyEvent( ModifyEvent::Type type )
   {
+    if( ModifyEvent::TEXT_REPLACED == type)
+    {
+      // Cancel previously queued inserts etc.
+      mModifyEvents.clear();
+    }
+
     ModifyEvent event;
     event.type = type;
     mModifyEvents.push_back( event );
index e07e29cdf9cd0ff3b9c0bac04cb1aa01d9b67ed1..889ca68600577ff4697d9008495c0151214685d4 100644 (file)
@@ -73,9 +73,6 @@ void Controller::EnableTextInput( DecoratorPtr decorator )
 
 void Controller::SetText( const std::string& text )
 {
-  // Cancel previously queued inserts etc.
-  mImpl->mModifyEvents.clear();
-
   // Remove the previously set text
   ResetText();
 
@@ -126,6 +123,9 @@ void Controller::SetText( const std::string& text )
 
   // Reset keyboard as text changed
   mImpl->ResetImfManager();
+
+  // Do this last since it provides callbacks into application code
+  mImpl->mControlInterface.TextChanged();
 }
 
 void Controller::GetText( std::string& text ) const
@@ -1089,6 +1089,8 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent )
 {
   DALI_ASSERT_DEBUG( mImpl->mEventData && "Unexpected KeyEvent" );
 
+  bool textChanged( false );
+
   if( mImpl->mEventData &&
       keyEvent.state == KeyEvent::Down )
   {
@@ -1131,6 +1133,8 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent )
         {
           mImpl->QueueModifyEvent( ModifyEvent::TEXT_DELETED );
         }
+
+        textChanged = true;
       }
     }
     else
@@ -1141,6 +1145,8 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent )
       mImpl->ClearPreEditFlag();
 
       InsertText( keyString, COMMIT );
+
+      textChanged = true;
     }
 
     mImpl->ChangeState( EventData::EDITING ); // todo Confirm this is the best place to change the state of
@@ -1148,6 +1154,12 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent )
     mImpl->RequestRelayout();
   }
 
+  if( textChanged )
+  {
+    // Do this last since it provides callbacks into application code
+    mImpl->mControlInterface.TextChanged();
+  }
+
   return false;
 }
 
@@ -1261,9 +1273,10 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ
   {
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "MaxLengthReached (%d)\n", mImpl->mLogicalModel->mText.Count() );
 
-    mImpl->mControlInterface.MaxLengthReached();
-
     mImpl->ResetImfManager();
+
+    // Do this last since it provides callbacks into application code
+    mImpl->mControlInterface.MaxLengthReached();
   }
 }
 
@@ -1432,6 +1445,9 @@ ImfManager::ImfCallbackData Controller::OnImfEvent( ImfManager& imfManager, cons
   {
     mImpl->mOperationsPending = ALL_OPERATIONS;
     mImpl->RequestRelayout();
+
+    // Do this last since it provides callbacks into application code
+    mImpl->mControlInterface.TextChanged();
   }
 
   ImfManager::ImfCallbackData callbackData( update, cursorPosition, text, false );
@@ -1453,9 +1469,6 @@ void Controller::ShowPlaceholderText()
 
     mImpl->mEventData->mIsShowingPlaceholderText = true;
 
-    // Cancel previously queued inserts etc.
-    mImpl->mModifyEvents.clear();
-
     // Disable handles when showing place-holder text
     mImpl->mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
     mImpl->mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
index 53401375d77289cf810e25cc1ddc5fe8c17f58e7..3a833f3e61cc6005b36d25b2fdb95f6c046c4e6c 100644 (file)
@@ -59,6 +59,11 @@ TextField TextField::DownCast( BaseHandle handle )
   return Control::DownCast<TextField, Internal::TextField>(handle);
 }
 
+TextField::TextChangedSignalType& TextField::TextChangedSignal()
+{
+  return Dali::Toolkit::GetImpl( *this ).TextChangedSignal();
+}
+
 TextField::MaxLengthReachedSignalType& TextField::MaxLengthReachedSignal()
 {
   return Dali::Toolkit::GetImpl( *this ).MaxLengthReachedSignal();
index 1f6df9b04905b62539233bf14ff90083a8f3df31..4f3da41f80e514c23c2e2649f80cb4fa09d91882 100644 (file)
@@ -38,6 +38,7 @@ class TextField;
  *  * Signals
  * | %Signal Name           | Method                                              |
  * |------------------------|-----------------------------------------------------|
+ * | text-changed           | @ref TextChangedSignal()                            |
  * | max-length-reached     | @ref MaxLengthReachedSignal()                       |
  *
  */
@@ -109,6 +110,7 @@ public:
   // Type Defs
 
   /// @brief Max Characters Exceed signal type;
+  typedef Signal<void ( TextField ) > TextChangedSignalType;
   typedef Signal<void ( TextField ) > MaxLengthReachedSignalType;
 
   /**
@@ -157,6 +159,17 @@ public:
 
   // Signals
 
+  /**
+   * @brief This signal is emitted when the text changes.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallbackName( TextField textField );
+   * @endcode
+   * @return The signal to connect to.
+   */
+  TextChangedSignalType& TextChangedSignal();
+
   /**
    * @brief This signal is emitted when inserted text exceeds the maximum character limit.
    *