Ensure UserDefined Font family is not changed by system font changing.
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-controller.cpp
index 47afc96..6b1e31f 100644 (file)
@@ -41,6 +41,7 @@ const float MAX_FLOAT = std::numeric_limits<float>::max();
 const unsigned int POINTS_PER_INCH = 72;
 
 const std::string EMPTY_STRING("");
+const unsigned int ZERO = 0u;
 
 float ConvertToEven( float value )
 {
@@ -76,6 +77,9 @@ void Controller::SetText( const std::string& text )
 {
   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SetText\n" );
 
+  // Reset keyboard as text changed
+  mImpl->ResetImfManager();
+
   // Remove the previously set text
   ResetText();
 
@@ -141,8 +145,8 @@ void Controller::SetText( const std::string& text )
     mImpl->mEventData->mEventQueue.clear();
   }
 
-  // Reset keyboard as text changed
-  mImpl->ResetImfManager();
+  // Notify IMF as text changed
+  NotifyImfManager();
 
   // Do this last since it provides callbacks into application code
   mImpl->mControlInterface.TextChanged();
@@ -225,15 +229,17 @@ int Controller::GetMaximumNumberOfCharacters()
   return mImpl->mMaximumNumberOfCharacters;
 }
 
-void Controller::SetDefaultFontFamily( const std::string& defaultFontFamily, bool userDefined )
+void Controller::SetDefaultFontFamily( const std::string& defaultFontFamily )
 {
   if( !mImpl->mFontDefaults )
   {
     mImpl->mFontDefaults = new FontDefaults();
   }
 
-  mImpl->mFontDefaults->mDefaultFontFamily = defaultFontFamily;
-  mImpl->mUserDefinedFontFamily = userDefined;
+  mImpl->mFontDefaults->mFontDescription.family = defaultFontFamily;
+  DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::SetDefaultFontFamily %s\n", defaultFontFamily.c_str());
+  mImpl->mUserDefinedFontFamily = true;
+
   // Clear the font-specific data
   ClearFontData();
 
@@ -247,20 +253,40 @@ const std::string& Controller::GetDefaultFontFamily() const
 {
   if( mImpl->mFontDefaults )
   {
-    return mImpl->mFontDefaults->mDefaultFontFamily;
+    return mImpl->mFontDefaults->mFontDescription.family;
   }
 
   return EMPTY_STRING;
 }
 
-void Controller::SetDefaultFontStyle( const std::string& defaultFontStyle )
+void Controller::SetDefaultFontStyle( const std::string& style )
 {
   if( !mImpl->mFontDefaults )
   {
     mImpl->mFontDefaults = new FontDefaults();
   }
 
-  mImpl->mFontDefaults->mDefaultFontStyle = defaultFontStyle;
+  mImpl->mFontDefaults->mFontStyle = style;
+}
+
+const std::string& Controller::GetDefaultFontStyle() const
+{
+  if( mImpl->mFontDefaults )
+  {
+    return mImpl->mFontDefaults->mFontStyle;
+  }
+
+  return EMPTY_STRING;
+}
+
+void Controller::SetDefaultFontWidth( FontWidth width )
+{
+  if( !mImpl->mFontDefaults )
+  {
+    mImpl->mFontDefaults = new FontDefaults();
+  }
+
+  mImpl->mFontDefaults->mFontDescription.width = width;
 
   // Clear the font-specific data
   ClearFontData();
@@ -271,14 +297,70 @@ void Controller::SetDefaultFontStyle( const std::string& defaultFontStyle )
   mImpl->RequestRelayout();
 }
 
-const std::string& Controller::GetDefaultFontStyle() const
+FontWidth Controller::GetDefaultFontWidth() const
 {
   if( mImpl->mFontDefaults )
   {
-    return mImpl->mFontDefaults->mDefaultFontStyle;
+    return mImpl->mFontDefaults->mFontDescription.width;
   }
 
-  return EMPTY_STRING;
+  return TextAbstraction::FontWidth::NORMAL;
+}
+
+void Controller::SetDefaultFontWeight( FontWeight weight )
+{
+  if( !mImpl->mFontDefaults )
+  {
+    mImpl->mFontDefaults = new FontDefaults();
+  }
+
+  mImpl->mFontDefaults->mFontDescription.weight = weight;
+
+  // Clear the font-specific data
+  ClearFontData();
+
+  mImpl->mOperationsPending = ALL_OPERATIONS;
+  mImpl->mRecalculateNaturalSize = true;
+
+  mImpl->RequestRelayout();
+}
+
+FontWeight Controller::GetDefaultFontWeight() const
+{
+  if( mImpl->mFontDefaults )
+  {
+    return mImpl->mFontDefaults->mFontDescription.weight;
+  }
+
+  return TextAbstraction::FontWeight::NORMAL;
+}
+
+void Controller::SetDefaultFontSlant( FontSlant slant )
+{
+  if( !mImpl->mFontDefaults )
+  {
+    mImpl->mFontDefaults = new FontDefaults();
+  }
+
+  mImpl->mFontDefaults->mFontDescription.slant = slant;
+
+  // Clear the font-specific data
+  ClearFontData();
+
+  mImpl->mOperationsPending = ALL_OPERATIONS;
+  mImpl->mRecalculateNaturalSize = true;
+
+  mImpl->RequestRelayout();
+}
+
+FontSlant Controller::GetDefaultFontSlant() const
+{
+  if( mImpl->mFontDefaults )
+  {
+    return mImpl->mFontDefaults->mFontDescription.slant;
+  }
+
+  return TextAbstraction::FontSlant::NORMAL;
 }
 
 void Controller::SetDefaultPointSize( float pointSize )
@@ -322,12 +404,11 @@ void Controller::UpdateAfterFontChange( std::string& newDefaultFont )
 {
   DALI_LOG_INFO( gLogFilter, Debug::Concise, "Controller::UpdateAfterFontChange");
 
-  ClearFontData();
-
   if ( !mImpl->mUserDefinedFontFamily ) // If user defined font then should not update when system font changes
   {
     DALI_LOG_INFO( gLogFilter, Debug::Concise, "Controller::UpdateAfterFontChange newDefaultFont(%s)\n", newDefaultFont.c_str() );
-    mImpl->mFontDefaults->mDefaultFontFamily=newDefaultFont;
+    ClearFontData();
+    mImpl->mFontDefaults->mFontDescription.family = newDefaultFont;
     mImpl->UpdateModel( ALL_OPERATIONS );
     mImpl->QueueModifyEvent( ModifyEvent::TEXT_REPLACED );
     mImpl->mRecalculateNaturalSize = true;
@@ -702,18 +783,18 @@ void Controller::ProcessModifyEvents()
 
   for( unsigned int i=0; i<events.size(); ++i )
   {
-    if( ModifyEvent::TEXT_REPLACED == events[0].type )
+    if( ModifyEvent::TEXT_REPLACED == events[i].type )
     {
       // A (single) replace event should come first, otherwise we wasted time processing NOOP events
       DALI_ASSERT_DEBUG( 0 == i && "Unexpected TEXT_REPLACED event" );
 
       TextReplacedEvent();
     }
-    else if( ModifyEvent::TEXT_INSERTED == events[0].type )
+    else if( ModifyEvent::TEXT_INSERTED == events[i].type )
     {
       TextInsertedEvent();
     }
-    else if( ModifyEvent::TEXT_DELETED == events[0].type )
+    else if( ModifyEvent::TEXT_DELETED == events[i].type )
     {
       // Placeholder-text cannot be deleted
       if( !mImpl->IsShowingPlaceholderText() )
@@ -1174,7 +1255,7 @@ void Controller::KeyboardFocusLostEvent()
     {
       mImpl->ChangeState( EventData::INACTIVE );
 
-      if( mImpl->IsShowingPlaceholderText() )
+      if( !mImpl->IsShowingRealText() )
       {
         // Revert to regular placeholder-text when not editing
         ShowPlaceholderText();
@@ -1441,6 +1522,11 @@ void Controller::TapEvent( unsigned int tapCount, float x, float y )
       else if( EventData::EDITING                  != mImpl->mEventData->mState &&
                EventData::EDITING_WITH_GRAB_HANDLE != mImpl->mEventData->mState )
       {
+        if( mImpl->IsShowingPlaceholderText() &&  ! mImpl->IsFocusedPlaceholderAvailable() )
+        {
+          // Hide placeholder text
+          ResetText();
+        }
         // Show cursor on first tap
         mImpl->ChangeState( EventData::EDITING );
         relayoutNeeded = true;
@@ -1495,21 +1581,41 @@ void Controller::PanEvent( Gesture::State state, const Vector2& displacement )
 
 void Controller::LongPressEvent( Gesture::State state, float x, float y  )
 {
-  DALI_ASSERT_DEBUG( mImpl->mEventData && "Unexpected PanEvent" );
+  DALI_ASSERT_DEBUG( mImpl->mEventData && "Unexpected LongPressEvent" );
 
-  if  ( mImpl->IsShowingPlaceholderText() || mImpl->mLogicalModel->mText.Count() == 0u )
+  if( state == Gesture::Started &&
+      mImpl->mEventData )
   {
-    if ( mImpl->mEventData )
+    if( ! mImpl->IsShowingRealText() )
     {
       Event event( Event::LONG_PRESS_EVENT );
       event.p1.mInt = state;
       mImpl->mEventData->mEventQueue.push_back( event );
       mImpl->RequestRelayout();
     }
-  }
-  else if( mImpl->mEventData )
-  {
-    SelectEvent( x, y, false );
+    else
+    {
+      // The 1st long-press on inactive text-field is treated as tap
+      if( EventData::INACTIVE == mImpl->mEventData->mState )
+      {
+        mImpl->ChangeState( EventData::EDITING );
+
+        Event event( Event::TAP_EVENT );
+        event.p1.mUint = 1;
+        event.p2.mFloat = x;
+        event.p3.mFloat = y;
+        mImpl->mEventData->mEventQueue.push_back( event );
+
+        mImpl->RequestRelayout();
+      }
+      else
+      {
+        // Reset the imf manger to commit the pre-edit before selecting the text.
+        mImpl->ResetImfManager();
+
+        SelectEvent( x, y, false );
+      }
+    }
   }
 }
 
@@ -1634,6 +1740,13 @@ void Controller::TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::Butt
     {
       mImpl->SendSelectionToClipboard( true ); // Synchronous call to modify text
       mImpl->mOperationsPending = ALL_OPERATIONS;
+
+      // This is to reset the virtual keyboard to Upper-case
+      if( 0u == mImpl->mLogicalModel->mText.Count() )
+      {
+        NotifyImfManager();
+      }
+
       if( 0u != mImpl->mLogicalModel->mText.Count() ||
           !mImpl->IsPlaceholderAvailable() )
       {
@@ -1704,6 +1817,7 @@ ImfManager::ImfCallbackData Controller::OnImfEvent( ImfManager& imfManager, cons
     case ImfManager::COMMIT:
     {
       InsertText( imfEvent.predictiveString, Text::Controller::COMMIT );
+      update=true;
       requestRelayout = true;
       break;
     }
@@ -1797,6 +1911,11 @@ bool Controller::BackspaceKeyEvent()
 
   if( removed )
   {
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::KeyEvent %p DALI_KEY_BACKSPACE RemovedText\n", this );
+    // Notifiy the IMF manager after text changed
+    // Automatic  Upper-case and restarting prediction on an existing word require this.
+    NotifyImfManager();
+
     if( 0u != mImpl->mLogicalModel->mText.Count() ||
         !mImpl->IsPlaceholderAvailable() )
     {
@@ -1812,6 +1931,25 @@ bool Controller::BackspaceKeyEvent()
   return removed;
 }
 
+void Controller::NotifyImfManager()
+{
+  if( mImpl->mEventData )
+  {
+    ImfManager imfManager = ImfManager::Get();
+
+    if( imfManager )
+    {
+      // Notifying IMF of a cursor change triggers a surrounding text request so updating it now.
+      std::string text;
+      GetText( text );
+      imfManager.SetSurroundingText( text );
+
+      imfManager.SetCursorPosition( GetLogicalCursorPosition() );
+      imfManager.NotifyCursorPosition();
+    }
+  }
+}
+
 void Controller::ShowPlaceholderText()
 {
   if( mImpl->IsPlaceholderAvailable() )