Added more DALI_LOG_INFO for Text components 84/38884/13
authorPaul Wisbey <p.wisbey@samsung.com>
Wed, 29 Apr 2015 16:04:53 +0000 (17:04 +0100)
committerPaul Wisbey <p.wisbey@samsung.com>
Fri, 1 May 2015 16:04:56 +0000 (17:04 +0100)
Enable Logging with environment variable
for general logging LOG_TEXT_CONTROLS=3,true
for verbose logging LOG_TEXT_CONTROLS=4,true

Change-Id: I58b02488875b6c72de28a9638d86dd68a0cb01dc

dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-controller-impl.h
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h

index 0dc5fd7..abefb7f 100644 (file)
@@ -28,8 +28,8 @@
 #include <dali/public-api/object/type-registry.h>
 #include <dali/public-api/object/type-registry-helper.h>
 #include <dali/public-api/scripting/scripting.h>
-#include <dali/integration-api/debug.h>
 #include <dali/public-api/adaptor-framework/virtual-keyboard.h>
+#include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/text/rendering-backend.h>
@@ -48,10 +48,16 @@ namespace Toolkit
 namespace Internal
 {
 
-namespace
+namespace // unnamed namespace
 {
+
+#if defined(DEBUG_ENABLED)
+  Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS");
+#endif
+
   const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
-}
+
+} // unnamed namespace
 
 namespace
 {
@@ -146,6 +152,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       case Toolkit::TextField::Property::RENDERING_BACKEND:
       {
         int backend = value.Get< int >();
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p RENDERING_BACKEND %d\n", impl.mController.Get(), backend );
 
         if( impl.mRenderingBackend != backend )
         {
@@ -158,7 +165,10 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       {
         if( impl.mController )
         {
-          impl.mController->SetText( value.Get< std::string >() );
+          std::string text = value.Get< std::string >();
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p TEXT %s\n", impl.mController.Get(), text.c_str() );
+
+          impl.mController->SetText( text );
         }
         break;
       }
@@ -166,7 +176,10 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       {
         if( impl.mController )
         {
-          impl.mController->SetPlaceholderText( PLACEHOLDER_TYPE_INACTIVE, value.Get< std::string >() );
+          std::string text = value.Get< std::string >();
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p PLACEHOLDER_TEXT %s\n", impl.mController.Get(), text.c_str() );
+
+          impl.mController->SetPlaceholderText( PLACEHOLDER_TYPE_INACTIVE, text );
         }
         break;
       }
@@ -174,7 +187,10 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       {
         if( impl.mController )
         {
-          impl.mController->SetPlaceholderText( PLACEHOLDER_TYPE_ACTIVE, value.Get< std::string >() );
+          std::string text = value.Get< std::string >();
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p PLACEHOLDER_TEXT_FOCUSED %s\n", impl.mController.Get(), text.c_str() );
+
+          impl.mController->SetPlaceholderText( PLACEHOLDER_TYPE_ACTIVE, text );
         }
         break;
       }
@@ -183,6 +199,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
         if( impl.mController )
         {
           std::string fontFamily = value.Get< std::string >();
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str() );
 
           if( impl.mController->GetDefaultFontFamily() != fontFamily )
           {
@@ -197,6 +214,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
         if( impl.mController )
         {
           std::string fontStyle = value.Get< std::string >();
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p FONT_STYLE %s\n", impl.mController.Get(), fontStyle.c_str() );
 
           if( impl.mController->GetDefaultFontStyle() != fontStyle )
           {
@@ -211,6 +229,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
         if( impl.mController )
         {
           float pointSize = value.Get< float >();
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p FONT_STYLE %f\n", impl.mController.Get(), pointSize );
 
           if( !Equals( impl.mController->GetDefaultPointSize(), pointSize ) )
           {
@@ -222,34 +241,46 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       }
       case Toolkit::TextField::Property::EXCEED_POLICY:
       {
-        impl.mExceedPolicy = value.Get< int >();
+        // TODO
         break;
       }
       case Toolkit::TextField::Property::HORIZONTAL_ALIGNMENT:
       {
-        LayoutEngine& engine = impl.mController->GetLayoutEngine();
-        const LayoutEngine::HorizontalAlignment alignment = Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::HorizontalAlignment >( value.Get< std::string >().c_str(),
-                                                                                                                                           HORIZONTAL_ALIGNMENT_STRING_TABLE,
-                                                                                                                                           HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
-
-        if( engine.GetHorizontalAlignment() != alignment )
+        if( impl.mController )
         {
-          engine.SetHorizontalAlignment( alignment );
-          impl.RequestTextRelayout();
+          std::string alignStr = value.Get< std::string >();
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p HORIZONTAL_ALIGNMENT %f\n", impl.mController.Get(), alignStr.c_str() );
+
+          LayoutEngine& engine = impl.mController->GetLayoutEngine();
+          LayoutEngine::HorizontalAlignment alignment = Scripting::GetEnumeration< LayoutEngine::HorizontalAlignment >( alignStr.c_str(),
+                                                                                                                        HORIZONTAL_ALIGNMENT_STRING_TABLE,
+                                                                                                                        HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
+
+          if( engine.GetHorizontalAlignment() != alignment )
+          {
+            engine.SetHorizontalAlignment( alignment );
+            impl.RequestTextRelayout();
+          }
         }
         break;
       }
       case Toolkit::TextField::Property::VERTICAL_ALIGNMENT:
       {
-        LayoutEngine& engine = impl.mController->GetLayoutEngine();
-        const LayoutEngine::VerticalAlignment alignment = Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::VerticalAlignment >( value.Get< std::string >().c_str(),
-                                                                                                                                       VERTICAL_ALIGNMENT_STRING_TABLE,
-                                                                                                                                       VERTICAL_ALIGNMENT_STRING_TABLE_COUNT );
-
-        if( engine.GetVerticalAlignment() != alignment )
+        if( impl.mController )
         {
-          engine.SetVerticalAlignment( alignment );
-          impl.RequestTextRelayout();
+          std::string alignStr = value.Get< std::string >();
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p VERTICAL_ALIGNMENT %f\n", impl.mController.Get(), alignStr.c_str() );
+
+          LayoutEngine& engine = impl.mController->GetLayoutEngine();
+          LayoutEngine::VerticalAlignment alignment = Scripting::GetEnumeration< LayoutEngine::VerticalAlignment >( alignStr.c_str(),
+                                                                                                                    VERTICAL_ALIGNMENT_STRING_TABLE,
+                                                                                                                    VERTICAL_ALIGNMENT_STRING_TABLE_COUNT );
+
+          if( engine.GetVerticalAlignment() != alignment )
+          {
+            engine.SetVerticalAlignment( alignment );
+            impl.RequestTextRelayout();
+          }
         }
         break;
       }
@@ -258,6 +289,8 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
         if ( impl.mController )
         {
           Vector4 textColor = value.Get< Vector4 >();
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p TEXT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), textColor.r, textColor.g, textColor.b, textColor.a );
+
           if ( impl.mController->GetTextColor() != textColor )
           {
             impl.mController->SetTextColor( textColor );
@@ -271,6 +304,8 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
         if ( impl.mController )
         {
           Vector4 textColor = value.Get< Vector4 >();
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p PLACEHOLDER_TEXT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), textColor.r, textColor.g, textColor.b, textColor.a );
+
           if ( impl.mController->GetPlaceholderTextColor() != textColor )
           {
             impl.mController->SetPlaceholderTextColor( textColor );
@@ -284,6 +319,8 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
         if( impl.mController )
         {
           Vector2 shadowOffset = value.Get< Vector2 >();
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p SHADOW_OFFSET %f,%f\n", impl.mController.Get(), shadowOffset.x, shadowOffset.y );
+
           if ( impl.mController->GetShadowOffset() != shadowOffset )
           {
             impl.mController->SetShadowOffset( shadowOffset );
@@ -297,6 +334,8 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
         if( impl.mController )
         {
           Vector4 shadowColor = value.Get< Vector4 >();
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p SHADOW_COLOR %f,%f,%f,%f\n", impl.mController.Get(), shadowColor.r, shadowColor.g, shadowColor.b, shadowColor.a );
+
           if ( impl.mController->GetShadowColor() != shadowColor )
           {
             impl.mController->SetShadowColor( shadowColor );
@@ -309,7 +348,10 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       {
         if( impl.mDecorator )
         {
-          impl.mDecorator->SetColor( PRIMARY_CURSOR, value.Get< Vector4 >() );
+          Vector4 color = value.Get< Vector4 >();
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p PRIMARY_CURSOR_COLOR %f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a );
+
+          impl.mDecorator->SetColor( PRIMARY_CURSOR, color );
         }
         break;
       }
@@ -317,7 +359,10 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       {
         if( impl.mDecorator )
         {
-          impl.mDecorator->SetColor( SECONDARY_CURSOR, value.Get< Vector4 >() );
+          Vector4 color = value.Get< Vector4 >();
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p SECONDARY_CURSOR_COLOR %f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a );
+
+          impl.mDecorator->SetColor( SECONDARY_CURSOR, color );
         }
         break;
       }
@@ -325,7 +370,10 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       {
         if( impl.mController )
         {
-          impl.mController->SetEnableCursorBlink( value.Get< bool >() );
+          bool enable = value.Get< bool >();
+          DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p ENABLE_CURSOR_BLINK %d\n", impl.mController.Get(), enable );
+
+          impl.mController->SetEnableCursorBlink( enable );
         }
         break;
       }
@@ -333,7 +381,10 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       {
         if( impl.mDecorator )
         {
-          impl.mDecorator->SetCursorBlinkInterval( value.Get< float >() );
+          float interval = value.Get< float >();
+          DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p CURSOR_BLINK_INTERVAL %f\n", impl.mController.Get(), interval );
+
+          impl.mDecorator->SetCursorBlinkInterval( interval );
         }
         break;
       }
@@ -341,13 +392,17 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       {
         if( impl.mDecorator )
         {
-          impl.mDecorator->SetCursorBlinkDuration( value.Get< float >() );
+          float duration = value.Get< float >();
+          DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p CURSOR_BLINK_INTERVAL %f\n", impl.mController.Get(), duration );
+
+          impl.mDecorator->SetCursorBlinkDuration( duration );
         }
         break;
       }
       case Toolkit::TextField::Property::GRAB_HANDLE_IMAGE:
       {
         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p GRAB_HANDLE_IMAGE %s\n", impl.mController.Get(), image.GetUrl().c_str() );
 
         if( impl.mDecorator )
         {
@@ -358,6 +413,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       case Toolkit::TextField::Property::GRAB_HANDLE_PRESSED_IMAGE:
       {
         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p GRAB_HANDLE_PRESSED_IMAGE %s\n", impl.mController.Get(), image.GetUrl().c_str() );
 
         if( impl.mDecorator )
         {
@@ -368,6 +424,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       case Toolkit::TextField::Property::SCROLL_THRESHOLD:
       {
         float threshold = value.Get< float >();
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p SCROLL_THRESHOLD %f\n", impl.mController.Get(), threshold );
 
         if( impl.mDecorator )
         {
@@ -378,6 +435,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       case Toolkit::TextField::Property::SCROLL_SPEED:
       {
         float speed = value.Get< float >();
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p SCROLL_SPEED %f\n", impl.mController.Get(), speed );
 
         if( impl.mDecorator )
         {
@@ -388,6 +446,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_LEFT:
       {
         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p SELECTION_HANDLE_IMAGE_LEFT %f\n", impl.mController.Get(), image.GetUrl().c_str() );
 
         if( impl.mDecorator )
         {
@@ -398,6 +457,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       case Toolkit::TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT:
       {
         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p SELECTION_HANDLE_IMAGE_RIGHT %f\n", impl.mController.Get(), image.GetUrl().c_str() );
 
         if( impl.mDecorator )
         {
@@ -408,6 +468,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT:
       {
         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p SELECTION_HANDLE_PRESSED_IMAGE_LEFT %f\n", impl.mController.Get(), image.GetUrl().c_str() );
 
         if( impl.mDecorator )
         {
@@ -418,6 +479,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       case Toolkit::TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT:
       {
         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p SELECTION_HANDLE_PRESSED_IMAGE_RIGHT %f\n", impl.mController.Get(), image.GetUrl().c_str() );
 
         if( impl.mDecorator )
         {
@@ -428,6 +490,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       case Toolkit::TextField::Property::SELECTION_HIGHLIGHT_COLOR:
       {
         Vector4 color = value.Get< Vector4 >();
+        DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p SELECTION_HIGHLIGHT_COLOR %f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a );
 
         if( impl.mDecorator )
         {
@@ -439,7 +502,10 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       {
         if( impl.mDecorator )
         {
-          impl.mDecorator->SetBoundingBox( value.Get< Rect<int> >() );
+          Rect<int> box = value.Get< Rect<int> >();
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p DECORATION_BOUNDING_BOX %d,%d %dx%d\n", impl.mController.Get(), box.x, box.y, box.width, box.height );
+
+          impl.mDecorator->SetBoundingBox( box );
         }
         break;
       }
@@ -447,7 +513,10 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
       {
         if( impl.mController )
         {
-          impl.mController->SetMaximumNumberOfCharacters( value.Get< int >() );
+          int max = value.Get< int >();
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p MAX_LENGTH %d\n", impl.mController.Get(), max );
+
+          impl.mController->SetMaximumNumberOfCharacters( max );
         }
         break;
       }
@@ -478,6 +547,7 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
         {
           std::string text;
           impl.mController->GetText( text );
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p returning text: %s\n", impl.mController.Get(), text.c_str() );
           value = text;
         }
         break;
@@ -788,6 +858,8 @@ void TextField::OnRelayout( const Vector2& size, RelayoutContainer& container )
   if( mController->Relayout( size ) ||
       !mRenderer )
   {
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnRelayout %p Displaying new contents\n", mController.Get() );
+
     if( mDecorator )
     {
       mDecorator->Relayout( size );
@@ -833,6 +905,8 @@ void TextField::OnRelayout( const Vector2& size, RelayoutContainer& container )
 
 void TextField::OnKeyInputFocusGained()
 {
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnKeyInputFocusGained %p\n", mController.Get() );
+
   VirtualKeyboard::StatusChangedSignal().Connect( this, &TextField::KeyboardStatusChanged );
 
   ImfManager imfManager = ImfManager::Get();
@@ -855,6 +929,8 @@ void TextField::OnKeyInputFocusGained()
 
 void TextField::OnKeyInputFocusLost()
 {
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField:OnKeyInputFocusLost %p\n", mController.Get() );
+
   VirtualKeyboard::StatusChangedSignal().Disconnect( this, &TextField::KeyboardStatusChanged );
 
   ImfManager imfManager = ImfManager::Get();
@@ -876,6 +952,8 @@ void TextField::OnKeyInputFocusLost()
 
 void TextField::OnTap( const TapGesture& gesture )
 {
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnTap %p\n", mController.Get() );
+
   // Show the keyboard if it was hidden.
   if (!VirtualKeyboard::IsVisible())
   {
@@ -895,6 +973,8 @@ void TextField::OnPan( const PanGesture& gesture )
 
 bool TextField::OnKeyEvent( const KeyEvent& event )
 {
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnKeyEvent %p keyCode %d\n", mController.Get(), event.keyCode );
+
   if( Dali::DALI_KEY_ESCAPE == event.keyCode ||
       "Return" == event.keyPressedName ) // Make a Dali key code for this
   {
@@ -907,6 +987,8 @@ bool TextField::OnKeyEvent( const KeyEvent& event )
 
 ImfManager::ImfCallbackData TextField::OnImfEvent( Dali::ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent )
 {
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnImfEvent %p eventName %d\n", imfEvent.eventName );
+
   bool update( false );
 
   std::string text;
@@ -998,6 +1080,8 @@ void TextField::EnableClipping( bool clipping, const Vector2& size )
 
 void TextField::KeyboardStatusChanged(bool keyboardShown)
 {
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::KeyboardStatusChanged %p keyboardShown %d\n", keyboardShown );
+
   // Just hide the grab handle when keyboard is hidden.
   if (!keyboardShown )
   {
index f39effe..49b8f3d 100644 (file)
@@ -238,83 +238,6 @@ bool Controller::Impl::ProcessInputEvents()
   return mEventData->mDecoratorUpdated;
 }
 
-void Controller::Impl::ReplaceTextWithPlaceholder()
-{
-  DALI_ASSERT_DEBUG( mEventData && "No placeholder text available" );
-  if( !mEventData )
-  {
-    return;
-  }
-
-  // Disable handles when showing place-holder text
-  mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
-  mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
-  mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
-
-  const char* text( NULL );
-  size_t size( 0 );
-
-  if( EventData::INACTIVE != mEventData->mState &&
-      0u != mEventData->mPlaceholderTextActive.c_str() )
-  {
-    text = mEventData->mPlaceholderTextActive.c_str();
-    size = mEventData->mPlaceholderTextActive.size();
-  }
-
-  else
-  {
-    text = mEventData->mPlaceholderTextInactive.c_str();
-    size = mEventData->mPlaceholderTextInactive.size();
-  }
-
-  // Reset buffers.
-  mLogicalModel->mText.Clear();
-  mLogicalModel->mScriptRuns.Clear();
-  mLogicalModel->mFontRuns.Clear();
-  mLogicalModel->mLineBreakInfo.Clear();
-  mLogicalModel->mWordBreakInfo.Clear();
-  mLogicalModel->mBidirectionalParagraphInfo.Clear();
-  mLogicalModel->mCharacterDirections.Clear();
-  mLogicalModel->mBidirectionalLineInfo.Clear();
-  mLogicalModel->mLogicalToVisualMap.Clear();
-  mLogicalModel->mVisualToLogicalMap.Clear();
-  mVisualModel->mGlyphs.Clear();
-  mVisualModel->mGlyphsToCharacters.Clear();
-  mVisualModel->mCharactersToGlyph.Clear();
-  mVisualModel->mCharactersPerGlyph.Clear();
-  mVisualModel->mGlyphsPerCharacter.Clear();
-  mVisualModel->mGlyphPositions.Clear();
-  mVisualModel->mLines.Clear();
-  mVisualModel->ClearCaches();
-  mVisualModel->SetTextColor( mEventData->mPlaceholderTextColor );
-
-  //  Convert text into UTF-32
-  Vector<Character>& utf32Characters = mLogicalModel->mText;
-  utf32Characters.Resize( size );
-
-  // This is a bit horrible but std::string returns a (signed) char*
-  const uint8_t* utf8 = reinterpret_cast<const uint8_t*>( text );
-
-  // Transform a text array encoded in utf8 into an array encoded in utf32.
-  // It returns the actual number of characters.
-  Length characterCount = Utf8ToUtf32( utf8, size, utf32Characters.Begin() );
-  utf32Characters.Resize( characterCount );
-
-  // Reset the cursor position
-  mEventData->mPrimaryCursorPosition = 0;
-
-  // The natural size needs to be re-calculated.
-  mRecalculateNaturalSize = true;
-
-  // Apply modifications to the model
-  mOperationsPending = ALL_OPERATIONS;
-  UpdateModel( ALL_OPERATIONS );
-  mOperationsPending = static_cast<OperationsMask>( LAYOUT             |
-                                                    ALIGN              |
-                                                    UPDATE_ACTUAL_SIZE |
-                                                    REORDER );
-}
-
 void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
 {
   // Calculate the operations to be done.
@@ -740,23 +663,8 @@ void Controller::Impl::ChangeState( EventData::State newState )
 
   if( mEventData->mState != newState )
   {
-    // Show different placeholder when switching between active & inactive
-    bool updatePlaceholder( false );
-    if( IsShowingPlaceholderText() &&
-        ( EventData::INACTIVE == newState ||
-          EventData::INACTIVE == mEventData->mState ) )
-    {
-      updatePlaceholder = true;
-    }
-
     mEventData->mState = newState;
 
-    if( updatePlaceholder )
-    {
-      ReplaceTextWithPlaceholder();
-      mEventData->mDecoratorUpdated = true;
-    }
-
     if( EventData::INACTIVE == mEventData->mState )
     {
       mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE );
index 9295d5f..7848541 100644 (file)
@@ -154,9 +154,8 @@ struct ModifyEvent
 {
   enum Type
   {
-    PLACEHOLDER_TEXT, ///< Show the placeholder text if necessary
     TEXT_REPLACED,    ///< The entire text was replaced
-    TEXT_INSERTED,      ///< Insert characters at the current cursor position
+    TEXT_INSERTED,    ///< Insert characters at the current cursor position
     TEXT_DELETED      ///< Characters were deleted
   };
 
@@ -263,17 +262,6 @@ struct Controller::Impl
     return ( mEventData && mEventData->mIsShowingPlaceholderText );
   }
 
-  void ShowPlaceholderText()
-  {
-    if( IsPlaceholderAvailable() )
-    {
-      mEventData->mIsShowingPlaceholderText = true;
-
-      // Placeholder-text is dependent on focus state i.e. replace after event processing
-      QueueModifyEvent( ModifyEvent::PLACEHOLDER_TEXT );
-    }
-  }
-
   /**
    * @brief Called when placeholder-text is hidden
    */
@@ -298,11 +286,6 @@ struct Controller::Impl
     }
   }
 
-  /**
-   * @brief Called when placeholder-text is shown
-   */
-  void ReplaceTextWithPlaceholder();
-
   void UpdateModel( OperationsMask operationsRequired );
 
   /**
index 95102d9..57356d0 100644 (file)
@@ -22,6 +22,7 @@
 #include <limits>
 #include <iostream>
 #include <dali/public-api/adaptor-framework/key.h>
+#include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/bidirectional-support.h>
 namespace
 {
 
+#if defined(DEBUG_ENABLED)
+  Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS");
+#endif
+
 const float MAX_FLOAT = std::numeric_limits<float>::max();
 
 const std::string EMPTY_STRING("");
@@ -58,6 +63,14 @@ ControllerPtr Controller::New( ControlInterface& controlInterface )
   return ControllerPtr( new Controller( controlInterface ) );
 }
 
+void Controller::EnableTextInput( DecoratorPtr decorator )
+{
+  if( !mImpl->mEventData )
+  {
+    mImpl->mEventData = new EventData( decorator );
+  }
+}
+
 void Controller::SetText( const std::string& text )
 {
   // Cancel previously queued inserts etc.
@@ -80,6 +93,9 @@ void Controller::SetText( const std::string& text )
     Length characterCount = Utf8ToUtf32( utf8, text.size(), utf32Characters.Begin() );
     utf32Characters.Resize( characterCount );
 
+    DALI_ASSERT_DEBUG( text.size() >= characterCount && "Invalid UTF32 conversion length" );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SetText %p UTF8 size %d, UTF32 size %d\n", this, text.size(), mImpl->mLogicalModel->mText.Count() );
+
     // Reset the cursor position
     if( mImpl->mEventData )
     {
@@ -91,7 +107,7 @@ void Controller::SetText( const std::string& text )
   }
   else
   {
-    mImpl->ShowPlaceholderText();
+    ShowPlaceholderText();
   }
 
   if( mImpl->mEventData )
@@ -120,6 +136,10 @@ void Controller::GetText( std::string& text ) const
       Utf32ToUtf8( &utf32Characters[0], utf32Characters.Count(), reinterpret_cast<uint8_t*>(&text[0]) );
     }
   }
+  else
+  {
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::GetText %p empty (but showing placeholder)\n", this );
+  }
 }
 
 unsigned int Controller::GetLogicalCursorPosition() const
@@ -145,7 +165,7 @@ void Controller::SetPlaceholderText( PlaceholderType type, const std::string& te
       mImpl->mEventData->mPlaceholderTextActive = text;
     }
 
-    mImpl->ShowPlaceholderText();
+    ShowPlaceholderText();
   }
 }
 
@@ -185,20 +205,12 @@ void Controller::SetDefaultFontFamily( const std::string& defaultFontFamily )
   }
 
   mImpl->mFontDefaults->mDefaultFontFamily = defaultFontFamily;
-  mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
-  mImpl->mOperationsPending = ALL_OPERATIONS;
-  mImpl->mRecalculateNaturalSize = true;
 
   // Clear the font-specific data
-  mImpl->mLogicalModel->mFontRuns.Clear();
-  mImpl->mVisualModel->mGlyphs.Clear();
-  mImpl->mVisualModel->mGlyphsToCharacters.Clear();
-  mImpl->mVisualModel->mCharactersToGlyph.Clear();
-  mImpl->mVisualModel->mCharactersPerGlyph.Clear();
-  mImpl->mVisualModel->mGlyphsPerCharacter.Clear();
-  mImpl->mVisualModel->mGlyphPositions.Clear();
-  mImpl->mVisualModel->mLines.Clear();
-  mImpl->mVisualModel->ClearCaches();
+  ClearFontData();
+
+  mImpl->mOperationsPending = ALL_OPERATIONS;
+  mImpl->mRecalculateNaturalSize = true;
 
   mImpl->RequestRelayout();
 }
@@ -221,20 +233,12 @@ void Controller::SetDefaultFontStyle( const std::string& defaultFontStyle )
   }
 
   mImpl->mFontDefaults->mDefaultFontStyle = defaultFontStyle;
-  mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
-  mImpl->mOperationsPending = ALL_OPERATIONS;
-  mImpl->mRecalculateNaturalSize = true;
 
   // Clear the font-specific data
-  mImpl->mLogicalModel->mFontRuns.Clear();
-  mImpl->mVisualModel->mGlyphs.Clear();
-  mImpl->mVisualModel->mGlyphsToCharacters.Clear();
-  mImpl->mVisualModel->mCharactersToGlyph.Clear();
-  mImpl->mVisualModel->mCharactersPerGlyph.Clear();
-  mImpl->mVisualModel->mGlyphsPerCharacter.Clear();
-  mImpl->mVisualModel->mGlyphPositions.Clear();
-  mImpl->mVisualModel->mLines.Clear();
-  mImpl->mVisualModel->ClearCaches();
+  ClearFontData();
+
+  mImpl->mOperationsPending = ALL_OPERATIONS;
+  mImpl->mRecalculateNaturalSize = true;
 
   mImpl->RequestRelayout();
 }
@@ -257,20 +261,12 @@ void Controller::SetDefaultPointSize( float pointSize )
   }
 
   mImpl->mFontDefaults->mDefaultPointSize = pointSize;
-  mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
-  mImpl->mOperationsPending = ALL_OPERATIONS;
-  mImpl->mRecalculateNaturalSize = true;
 
   // Clear the font-specific data
-  mImpl->mLogicalModel->mFontRuns.Clear();
-  mImpl->mVisualModel->mGlyphs.Clear();
-  mImpl->mVisualModel->mGlyphsToCharacters.Clear();
-  mImpl->mVisualModel->mCharactersToGlyph.Clear();
-  mImpl->mVisualModel->mCharactersPerGlyph.Clear();
-  mImpl->mVisualModel->mGlyphsPerCharacter.Clear();
-  mImpl->mVisualModel->mGlyphPositions.Clear();
-  mImpl->mVisualModel->mLines.Clear();
-  mImpl->mVisualModel->ClearCaches();
+  ClearFontData();
+
+  mImpl->mOperationsPending = ALL_OPERATIONS;
+  mImpl->mRecalculateNaturalSize = true;
 
   mImpl->RequestRelayout();
 }
@@ -304,6 +300,9 @@ bool Controller::RemoveText( int cursorOffset, int numberOfChars )
 {
   bool removed( false );
 
+  DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::RemoveText %p mText.Count() %d cursor %d cursorOffset %d numberOfChars %d\n",
+                 this, mImpl->mLogicalModel->mText.Count(), mImpl->mEventData->mPrimaryCursorPosition, cursorOffset, numberOfChars );
+
   if( ! mImpl->IsShowingPlaceholderText() )
   {
     // Delete at current cursor position
@@ -334,6 +333,7 @@ bool Controller::RemoveText( int cursorOffset, int numberOfChars )
       // Cursor position retreat
       oldCursorIndex = cursorIndex;
 
+      DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::RemoveText %p removed %d\n", this, numberOfChars );
       removed = true;
     }
   }
@@ -414,14 +414,6 @@ float Controller::GetUnderlineHeight() const
   return mImpl->mVisualModel->GetUnderlineHeight();
 }
 
-void Controller::EnableTextInput( DecoratorPtr decorator )
-{
-  if( !mImpl->mEventData )
-  {
-    mImpl->mEventData = new EventData( decorator );
-  }
-}
-
 void Controller::SetEnableCursorBlink( bool enable )
 {
   DALI_ASSERT_DEBUG( NULL != mImpl->mEventData && "TextInput disabled" );
@@ -560,6 +552,8 @@ float Controller::GetHeightForWidth( float width )
 
 bool Controller::Relayout( const Size& size )
 {
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::Relayout %p --> size %f,%f\n", this, size.width, size.height );
+
   if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
   {
     bool glyphsRemoved( false );
@@ -569,11 +563,14 @@ bool Controller::Relayout( const Size& size )
       glyphsRemoved = true;
     }
     // Not worth to relayout if width or height is equal to zero.
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::Relayout <-- (skipped)\n" );
     return glyphsRemoved;
   }
 
   if( size != mImpl->mControlSize )
   {
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "new size (previous size %f,%f)\n", mImpl->mControlSize.width, mImpl->mControlSize.height );
+
     // Operations that need to be done if the size changes.
     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
                                                              LAYOUT                    |
@@ -605,6 +602,7 @@ bool Controller::Relayout( const Size& size )
     updated = mImpl->ProcessInputEvents() || updated;
   }
 
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::Relayout <--\n" );
   return updated;
 }
 
@@ -614,16 +612,7 @@ void Controller::ProcessModifyEvents()
 
   for( unsigned int i=0; i<events.size(); ++i )
   {
-    if( ModifyEvent::PLACEHOLDER_TEXT == events[0].type )
-    {
-      // Use placeholder if text is empty
-      if( 0u == mImpl->mLogicalModel->mText.Count() &&
-          mImpl->IsShowingPlaceholderText() )
-      {
-        mImpl->ReplaceTextWithPlaceholder();
-      }
-    }
-    else if( ModifyEvent::TEXT_REPLACED == events[0].type )
+    if( ModifyEvent::TEXT_REPLACED == events[0].type )
     {
       // A (single) replace event should come first, otherwise we wasted time processing NOOP events
       DALI_ASSERT_DEBUG( 0 == i && "Unexpected TEXT_REPLACED event" );
@@ -652,23 +641,7 @@ void Controller::ResetText()
 {
   // Reset buffers.
   mImpl->mLogicalModel->mText.Clear();
-  mImpl->mLogicalModel->mScriptRuns.Clear();
-  mImpl->mLogicalModel->mFontRuns.Clear();
-  mImpl->mLogicalModel->mLineBreakInfo.Clear();
-  mImpl->mLogicalModel->mWordBreakInfo.Clear();
-  mImpl->mLogicalModel->mBidirectionalParagraphInfo.Clear();
-  mImpl->mLogicalModel->mCharacterDirections.Clear();
-  mImpl->mLogicalModel->mBidirectionalLineInfo.Clear();
-  mImpl->mLogicalModel->mLogicalToVisualMap.Clear();
-  mImpl->mLogicalModel->mVisualToLogicalMap.Clear();
-  mImpl->mVisualModel->mGlyphs.Clear();
-  mImpl->mVisualModel->mGlyphsToCharacters.Clear();
-  mImpl->mVisualModel->mCharactersToGlyph.Clear();
-  mImpl->mVisualModel->mCharactersPerGlyph.Clear();
-  mImpl->mVisualModel->mGlyphsPerCharacter.Clear();
-  mImpl->mVisualModel->mGlyphPositions.Clear();
-  mImpl->mVisualModel->mLines.Clear();
-  mImpl->mVisualModel->ClearCaches();
+  ClearModelData();
 
   // Reset the cursor position
   if( mImpl->mEventData )
@@ -689,23 +662,7 @@ void Controller::ResetText()
 void Controller::TextReplacedEvent()
 {
   // Reset buffers.
-  mImpl->mLogicalModel->mScriptRuns.Clear();
-  mImpl->mLogicalModel->mFontRuns.Clear();
-  mImpl->mLogicalModel->mLineBreakInfo.Clear();
-  mImpl->mLogicalModel->mWordBreakInfo.Clear();
-  mImpl->mLogicalModel->mBidirectionalParagraphInfo.Clear();
-  mImpl->mLogicalModel->mCharacterDirections.Clear();
-  mImpl->mLogicalModel->mBidirectionalLineInfo.Clear();
-  mImpl->mLogicalModel->mLogicalToVisualMap.Clear();
-  mImpl->mLogicalModel->mVisualToLogicalMap.Clear();
-  mImpl->mVisualModel->mGlyphs.Clear();
-  mImpl->mVisualModel->mGlyphsToCharacters.Clear();
-  mImpl->mVisualModel->mCharactersToGlyph.Clear();
-  mImpl->mVisualModel->mCharactersPerGlyph.Clear();
-  mImpl->mVisualModel->mGlyphsPerCharacter.Clear();
-  mImpl->mVisualModel->mGlyphPositions.Clear();
-  mImpl->mVisualModel->mLines.Clear();
-  mImpl->mVisualModel->ClearCaches();
+  ClearModelData();
 
   // The natural size needs to be re-calculated.
   mImpl->mRecalculateNaturalSize = true;
@@ -724,23 +681,7 @@ void Controller::TextInsertedEvent()
   DALI_ASSERT_DEBUG( NULL != mImpl->mEventData && "Unexpected TextInsertedEvent" );
 
   // TODO - Optimize this
-  mImpl->mLogicalModel->mScriptRuns.Clear();
-  mImpl->mLogicalModel->mFontRuns.Clear();
-  mImpl->mLogicalModel->mLineBreakInfo.Clear();
-  mImpl->mLogicalModel->mWordBreakInfo.Clear();
-  mImpl->mLogicalModel->mBidirectionalParagraphInfo.Clear();
-  mImpl->mLogicalModel->mCharacterDirections.Clear();
-  mImpl->mLogicalModel->mBidirectionalLineInfo.Clear();
-  mImpl->mLogicalModel->mLogicalToVisualMap.Clear();
-  mImpl->mLogicalModel->mVisualToLogicalMap.Clear();
-  mImpl->mVisualModel->mGlyphs.Clear();
-  mImpl->mVisualModel->mGlyphsToCharacters.Clear();
-  mImpl->mVisualModel->mCharactersToGlyph.Clear();
-  mImpl->mVisualModel->mCharactersPerGlyph.Clear();
-  mImpl->mVisualModel->mGlyphsPerCharacter.Clear();
-  mImpl->mVisualModel->mGlyphPositions.Clear();
-  mImpl->mVisualModel->mLines.Clear();
-  mImpl->mVisualModel->ClearCaches();
+  ClearModelData();
 
   // The natural size needs to be re-calculated.
   mImpl->mRecalculateNaturalSize = true;
@@ -763,23 +704,7 @@ void Controller::TextDeletedEvent()
   DALI_ASSERT_DEBUG( NULL != mImpl->mEventData && "Unexpected TextDeletedEvent" );
 
   // TODO - Optimize this
-  mImpl->mLogicalModel->mScriptRuns.Clear();
-  mImpl->mLogicalModel->mFontRuns.Clear();
-  mImpl->mLogicalModel->mLineBreakInfo.Clear();
-  mImpl->mLogicalModel->mWordBreakInfo.Clear();
-  mImpl->mLogicalModel->mBidirectionalParagraphInfo.Clear();
-  mImpl->mLogicalModel->mCharacterDirections.Clear();
-  mImpl->mLogicalModel->mBidirectionalLineInfo.Clear();
-  mImpl->mLogicalModel->mLogicalToVisualMap.Clear();
-  mImpl->mLogicalModel->mVisualToLogicalMap.Clear();
-  mImpl->mVisualModel->mGlyphs.Clear();
-  mImpl->mVisualModel->mGlyphsToCharacters.Clear();
-  mImpl->mVisualModel->mCharactersToGlyph.Clear();
-  mImpl->mVisualModel->mCharactersPerGlyph.Clear();
-  mImpl->mVisualModel->mGlyphsPerCharacter.Clear();
-  mImpl->mVisualModel->mGlyphPositions.Clear();
-  mImpl->mVisualModel->mLines.Clear();
-  mImpl->mVisualModel->ClearCaches();
+  ClearModelData();
 
   // The natural size needs to be re-calculated.
   mImpl->mRecalculateNaturalSize = true;
@@ -1069,7 +994,7 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent )
       {
         if( 0u == mImpl->mLogicalModel->mText.Count() )
         {
-          mImpl->ShowPlaceholderText();
+          ShowPlaceholderText();
         }
         else
         {
@@ -1095,6 +1020,10 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ
   bool removedPreEdit( false );
   bool maxLengthReached( false );
 
+  DALI_ASSERT_DEBUG( NULL != mImpl->mEventData && "Unexpected InsertText" )
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::InsertText %p %s (%s) mPreEditFlag %d cursor %d\n",
+                 this, text.c_str(), (COMMIT == type ? "COMMIT" : "PRE_EDIT"), mImpl->mEventData->mPreEditFlag, mImpl->mEventData->mPrimaryCursorPosition );
+
   if( ! text.empty() )
   {
     if( mImpl->IsShowingPlaceholderText() )
@@ -1123,6 +1052,8 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ
         // Record the start of the pre-edit text
         mImpl->mEventData->mPreEditStartPosition = mImpl->mEventData->mPrimaryCursorPosition;
         mImpl->mEventData->mPreEditLength = text.size();
+
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "mPreEditStartPosition %d mPreEditLength %d\n", mImpl->mEventData->mPreEditStartPosition, mImpl->mEventData->mPreEditLength );
       }
 
       mImpl->mEventData->mPreEditFlag = true;
@@ -1143,6 +1074,9 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ
     Length characterCount = Utf8ToUtf32( utf8, text.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() );
+
     const Length numberOfCharactersInModel = mImpl->mLogicalModel->GetNumberOfCharacters();
 
     // Restrict new text to fit within Maximum characters setting
@@ -1164,6 +1098,8 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ
     }
 
     cursorIndex += maxSizeOfNewText;
+
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Inserted %d characters, new size %d new cursor %d\n", maxSizeOfNewText, mImpl->mLogicalModel->mText.Count(), mImpl->mEventData->mPrimaryCursorPosition );
   }
 
   if( removedPreEdit || !text.empty() )
@@ -1174,6 +1110,8 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ
 
   if( maxLengthReached )
   {
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "MaxLengthReached (%d)\n", mImpl->mLogicalModel->mText.Count() );
+
     mImpl->mControlInterface.MaxLengthReached();
 
     mImpl->PreEditReset();
@@ -1268,6 +1206,100 @@ Controller::~Controller()
   delete mImpl;
 }
 
+void Controller::ShowPlaceholderText()
+{
+  if( mImpl->IsPlaceholderAvailable() )
+  {
+    DALI_ASSERT_DEBUG( mImpl->mEventData && "No placeholder text available" );
+
+    mImpl->mEventData->mIsShowingPlaceholderText = true;
+
+    // Disable handles when showing place-holder text
+    mImpl->mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
+    mImpl->mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
+    mImpl->mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
+
+    const char* text( NULL );
+    size_t size( 0 );
+
+    // TODO - Switch placeholder text styles when changing state
+    if( EventData::INACTIVE != mImpl->mEventData->mState &&
+        0u != mImpl->mEventData->mPlaceholderTextActive.c_str() )
+    {
+      text = mImpl->mEventData->mPlaceholderTextActive.c_str();
+      size = mImpl->mEventData->mPlaceholderTextActive.size();
+    }
+    else
+    {
+      text = mImpl->mEventData->mPlaceholderTextInactive.c_str();
+      size = mImpl->mEventData->mPlaceholderTextInactive.size();
+    }
+
+    // Reset model for showing placeholder.
+    mImpl->mLogicalModel->mText.Clear();
+    ClearModelData();
+    mImpl->mVisualModel->SetTextColor( mImpl->mEventData->mPlaceholderTextColor );
+
+    // Convert text into UTF-32
+    Vector<Character>& utf32Characters = mImpl->mLogicalModel->mText;
+    utf32Characters.Resize( size );
+
+    // This is a bit horrible but std::string returns a (signed) char*
+    const uint8_t* utf8 = reinterpret_cast<const uint8_t*>( text );
+
+    // Transform a text array encoded in utf8 into an array encoded in utf32.
+    // It returns the actual number of characters.
+    Length characterCount = Utf8ToUtf32( utf8, size, utf32Characters.Begin() );
+    utf32Characters.Resize( characterCount );
+
+    // Reset the cursor position
+    mImpl->mEventData->mPrimaryCursorPosition = 0;
+
+    // The natural size needs to be re-calculated.
+    mImpl->mRecalculateNaturalSize = true;
+
+    // Apply modifications to the model
+    mImpl->mOperationsPending = ALL_OPERATIONS;
+    mImpl->QueueModifyEvent( ModifyEvent::TEXT_REPLACED );
+  }
+}
+
+void Controller::ClearModelData()
+{
+  // n.b. This does not Clear the mText from mLogicalModel
+  mImpl->mLogicalModel->mScriptRuns.Clear();
+  mImpl->mLogicalModel->mFontRuns.Clear();
+  mImpl->mLogicalModel->mLineBreakInfo.Clear();
+  mImpl->mLogicalModel->mWordBreakInfo.Clear();
+  mImpl->mLogicalModel->mBidirectionalParagraphInfo.Clear();
+  mImpl->mLogicalModel->mCharacterDirections.Clear();
+  mImpl->mLogicalModel->mBidirectionalLineInfo.Clear();
+  mImpl->mLogicalModel->mLogicalToVisualMap.Clear();
+  mImpl->mLogicalModel->mVisualToLogicalMap.Clear();
+  mImpl->mVisualModel->mGlyphs.Clear();
+  mImpl->mVisualModel->mGlyphsToCharacters.Clear();
+  mImpl->mVisualModel->mCharactersToGlyph.Clear();
+  mImpl->mVisualModel->mCharactersPerGlyph.Clear();
+  mImpl->mVisualModel->mGlyphsPerCharacter.Clear();
+  mImpl->mVisualModel->mGlyphPositions.Clear();
+  mImpl->mVisualModel->mLines.Clear();
+  mImpl->mVisualModel->ClearCaches();
+}
+
+void Controller::ClearFontData()
+{
+  mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
+  mImpl->mLogicalModel->mFontRuns.Clear();
+  mImpl->mVisualModel->mGlyphs.Clear();
+  mImpl->mVisualModel->mGlyphsToCharacters.Clear();
+  mImpl->mVisualModel->mCharactersToGlyph.Clear();
+  mImpl->mVisualModel->mCharactersPerGlyph.Clear();
+  mImpl->mVisualModel->mGlyphsPerCharacter.Clear();
+  mImpl->mVisualModel->mGlyphPositions.Clear();
+  mImpl->mVisualModel->mLines.Clear();
+  mImpl->mVisualModel->ClearCaches();
+}
+
 Controller::Controller( ControlInterface& controlInterface )
 : mImpl( NULL )
 {
index 4edd281..63ec1c3 100644 (file)
@@ -110,6 +110,14 @@ public:
   static ControllerPtr New( ControlInterface& controlInterface );
 
   /**
+   * @brief Called to enable text input.
+   *
+   * @note Selectable or editable controls should call this once after Controller::New().
+   * @param[in] decorator Used to create cursor, selection handle decorations etc.
+   */
+  void EnableTextInput( DecoratorPtr decorator );
+
+  /**
    * @brief Replaces any text previously set.
    *
    * @note This will be converted into UTF-32 when stored in the text model.
@@ -311,14 +319,6 @@ public:
   float GetUnderlineHeight() const;
 
   /**
-   * @brief Called to enable text input.
-   *
-   * @note Only selectable or editable controls should calls this.
-   * @param[in] decorator Used to create cursor, selection handle decorations etc.
-   */
-  void EnableTextInput( DecoratorPtr decorator );
-
-  /**
    * @brief Called to enable/disable cursor blink.
    *
    * @note Only editable controls should calls this.
@@ -484,6 +484,21 @@ protected:
 private:
 
   /**
+   * @brief Helper to clear font-specific data.
+   */
+  void ShowPlaceholderText();
+
+  /**
+   * @brief Helper to clear all the model data except for LogicalModel::mText.
+   */
+  void ClearModelData();
+
+  /**
+   * @brief Helper to clear font-specific data (only).
+   */
+  void ClearFontData();
+
+  /**
    * @brief Private constructor.
    */
   Controller( ControlInterface& controlInterface );