Call VirtualKeyboard ApplySettings
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / text-controls / text-field-impl.cpp
index 5074cdc..da4a593 100644 (file)
 
 // EXTERNAL INCLUDES
 #include <string>
+#include <iostream>
+#include <cstring>
 #include <dali/public-api/adaptor-framework/key.h>
 #include <dali/public-api/common/stage.h>
 #include <dali/public-api/images/resource-image.h>
 #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/devel-api/object/type-registry-helper.h>
+#include <dali/devel-api/scripting/scripting.h>
+#include <dali/devel-api/adaptor-framework/virtual-keyboard.h>
 #include <dali/integration-api/debug.h>
-#include <dali/public-api/adaptor-framework/virtual-keyboard.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/text/rendering-backend.h>
@@ -46,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
 {
@@ -80,15 +88,18 @@ BaseHandle Create()
 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextField, Toolkit::Control, Create );
 
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "rendering-backend",                    INTEGER,   RENDERING_BACKEND                    )
-DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "placeholder-text",                     STRING,    PLACEHOLDER_TEXT                     )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "text",                                 STRING,    TEXT                                 )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "placeholder-text",                     STRING,    PLACEHOLDER_TEXT                     )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "placeholder-text-focused",             STRING,    PLACEHOLDER_TEXT_FOCUSED             )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "font-family",                          STRING,    FONT_FAMILY                          )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "font-style",                           STRING,    FONT_STYLE                           )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "point-size",                           FLOAT,     POINT_SIZE                           )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "max-length",                           INTEGER,   MAX_LENGTH                           )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "exceed-policy",                        INTEGER,   EXCEED_POLICY                        )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "horizontal-alignment",                 STRING,    HORIZONTAL_ALIGNMENT                 )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "vertical-alignment",                   STRING,    VERTICAL_ALIGNMENT                   )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "text-color",                           VECTOR4,   TEXT_COLOR                           )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "placeholder-text-color",               VECTOR4,   PLACEHOLDER_TEXT_COLOR               )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "shadow-offset",                        VECTOR2,   SHADOW_OFFSET                        )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "shadow-color",                         VECTOR4,   SHADOW_COLOR                         )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "primary-cursor-color",                 VECTOR4,   PRIMARY_CURSOR_COLOR                 )
@@ -106,6 +117,9 @@ DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "selection-handle-pressed-image-
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "selection-handle-pressed-image-right", STRING,    SELECTION_HANDLE_PRESSED_IMAGE_RIGHT )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "selection-highlight-color",            STRING,    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, "max-length-reached", SIGNAL_MAX_LENGTH_REACHED )
 
 DALI_TYPE_REGISTRATION_END()
 
@@ -139,6 +153,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 )
         {
@@ -147,19 +162,36 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
         }
         break;
       }
+      case Toolkit::TextField::Property::TEXT:
+      {
+        if( impl.mController )
+        {
+          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;
+      }
       case Toolkit::TextField::Property::PLACEHOLDER_TEXT:
       {
         if( impl.mController )
         {
-          //impl.mController->SetPlaceholderText( value.Get< std::string >() ); TODO
+          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;
       }
-      case Toolkit::TextField::Property::TEXT:
+      case Toolkit::TextField::Property::PLACEHOLDER_TEXT_FOCUSED:
       {
         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 PLACEHOLDER_TEXT_FOCUSED %s\n", impl.mController.Get(), text.c_str() );
+
+          impl.mController->SetPlaceholderText( PLACEHOLDER_TYPE_ACTIVE, text );
         }
         break;
       }
@@ -168,6 +200,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 )
           {
@@ -182,6 +215,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 )
           {
@@ -196,6 +230,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 ) )
           {
@@ -207,34 +242,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;
       }
@@ -243,6 +290,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 );
@@ -251,11 +300,28 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
         }
         break;
       }
+      case Toolkit::TextField::Property::PLACEHOLDER_TEXT_COLOR:
+      {
+        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 );
+            impl.RequestTextRelayout();
+          }
+        }
+        break;
+      }
       case Toolkit::TextField::Property::SHADOW_OFFSET:
       {
         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 );
@@ -269,6 +335,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 );
@@ -281,7 +349,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;
       }
@@ -289,7 +360,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;
       }
@@ -297,7 +371,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;
       }
@@ -305,7 +382,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;
       }
@@ -313,33 +393,39 @@ 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 )
         {
-          impl.mDecorator->SetGrabHandleImage( GRAB_HANDLE_IMAGE_RELEASED, image );
+          impl.mDecorator->SetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_RELEASED, image );
         }
         break;
       }
       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 )
         {
-          impl.mDecorator->SetGrabHandleImage( GRAB_HANDLE_IMAGE_PRESSED, image );
+          impl.mDecorator->SetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_PRESSED, image );
         }
         break;
       }
       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 )
         {
@@ -350,6 +436,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 )
         {
@@ -360,46 +447,51 @@ 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 )
         {
-          impl.mDecorator->SetLeftSelectionImage( SELECTION_HANDLE_RELEASED, image );
+          impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, image );
         }
         break;
       }
       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 )
         {
-          impl.mDecorator->SetRightSelectionImage( SELECTION_HANDLE_RELEASED, image );
+          impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, image );
         }
         break;
       }
       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 )
         {
-          impl.mDecorator->SetLeftSelectionImage( SELECTION_HANDLE_PRESSED, image );
+          impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, image );
         }
         break;
       }
       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 )
         {
-          impl.mDecorator->SetLeftSelectionImage( SELECTION_HANDLE_PRESSED, image );
+          impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, image );
         }
         break;
       }
       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 )
         {
@@ -411,10 +503,31 @@ 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;
+      }
+      case Toolkit::TextField::Property::MAX_LENGTH:
+      {
+        if( impl.mController )
+        {
+          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;
       }
+      case Toolkit::TextField::Property::INPUT_METHOD_SETTINGS:
+      {
+        // Empty implementation for now.
+        Property::Map map = value.Get<Property::Map>();
+        VirtualKeyboard::ApplySettings( map );
+        break;
+      }
     } // switch
   } // textfield
 }
@@ -436,22 +549,33 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
         value = impl.mRenderingBackend;
         break;
       }
+      case Toolkit::TextField::Property::TEXT:
+      {
+        if( impl.mController )
+        {
+          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;
+      }
       case Toolkit::TextField::Property::PLACEHOLDER_TEXT:
       {
         if( impl.mController )
         {
           std::string text;
-          impl.mController->GetPlaceholderText( text );
+          impl.mController->GetPlaceholderText( PLACEHOLDER_TYPE_INACTIVE, text );
           value = text;
         }
         break;
       }
-      case Toolkit::TextField::Property::TEXT:
+      case Toolkit::TextField::Property::PLACEHOLDER_TEXT_FOCUSED:
       {
         if( impl.mController )
         {
           std::string text;
-          impl.mController->GetText( text );
+          impl.mController->GetPlaceholderText( PLACEHOLDER_TYPE_ACTIVE, text );
           value = text;
         }
         break;
@@ -489,6 +613,14 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
         }
         break;
       }
+      case Toolkit::TextField::Property::PLACEHOLDER_TEXT_COLOR:
+      {
+        if ( impl.mController )
+        {
+          value = impl.mController->GetPlaceholderTextColor();
+        }
+        break;
+      }
       case Toolkit::TextField::Property::SHADOW_OFFSET:
       {
         if ( impl.mController )
@@ -546,7 +678,7 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
       {
         if( impl.mDecorator )
         {
-          ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetGrabHandleImage( GRAB_HANDLE_IMAGE_RELEASED ) );
+          ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_RELEASED ) );
           if( image )
           {
             value = image.GetUrl();
@@ -558,7 +690,7 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
       {
         if( impl.mDecorator )
         {
-          ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetGrabHandleImage( GRAB_HANDLE_IMAGE_PRESSED ) );
+          ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_PRESSED ) );
           if( image )
           {
             value = image.GetUrl();
@@ -586,7 +718,7 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
       {
         if( impl.mDecorator )
         {
-          ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetLeftSelectionImage( SELECTION_HANDLE_RELEASED ) );
+          ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED ) );
           if( image )
           {
             value = image.GetUrl();
@@ -598,7 +730,7 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
       {
         if( impl.mDecorator )
         {
-          ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetRightSelectionImage( SELECTION_HANDLE_RELEASED ) );
+          ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED ) );
           if( image )
           {
             value = image.GetUrl();
@@ -610,7 +742,7 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
       {
         if( impl.mDecorator )
         {
-          ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetLeftSelectionImage( SELECTION_HANDLE_PRESSED ) );
+          ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED ) );
           if( image )
           {
             value = image.GetUrl();
@@ -622,7 +754,7 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
       {
         if( impl.mDecorator )
         {
-          ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetRightSelectionImage( SELECTION_HANDLE_PRESSED ) );
+          ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED ) );
           if( image )
           {
             value = image.GetUrl();
@@ -646,12 +778,49 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
         }
         break;
       }
+      case Toolkit::TextField::Property::MAX_LENGTH:
+      {
+        if( impl.mController )
+        {
+          value = impl.mController->GetMaximumNumberOfCharacters();
+        }
+        break;
+      }
+      case Toolkit::TextField::Property::INPUT_METHOD_SETTINGS:
+      {
+        break;
+      }
     } //switch
   }
 
   return value;
 }
 
+bool TextField::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  Dali::BaseHandle handle( object );
+
+  bool connected( true );
+  Toolkit::TextField field = Toolkit::TextField::DownCast( handle );
+
+  if( 0 == strcmp( signalName.c_str(), SIGNAL_MAX_LENGTH_REACHED ) )
+  {
+    field.MaxLengthReachedSignal().Connect( tracker, functor );
+  }
+  else
+  {
+    // signalName does not match any signal
+    connected = false;
+  }
+
+  return connected;
+}
+
+Toolkit::TextField::MaxLengthReachedSignalType& TextField::MaxLengthReachedSignal()
+{
+  return mMaxLengthReachedSignal;
+}
+
 void TextField::OnInitialize()
 {
   Actor self = Self();
@@ -681,7 +850,7 @@ void TextField::OnInitialize()
   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
 }
 
-void TextField::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change )
+void TextField::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
 {
   GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
 }
@@ -701,6 +870,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 );
@@ -746,6 +917,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();
@@ -768,6 +941,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();
@@ -789,15 +964,18 @@ 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())
   {
     VirtualKeyboard::Show();
   }
 
-  SetKeyInputFocus();
-
+  // Deliver the tap before the focus event to controller; this allows us to detect when focus is gained due to tap-gestures
   mController->TapEvent( gesture.numberOfTaps, gesture.localPoint.x, gesture.localPoint.y );
+
+  SetKeyInputFocus();
 }
 
 void TextField::OnPan( const PanGesture& gesture )
@@ -807,9 +985,13 @@ void TextField::OnPan( const PanGesture& gesture )
 
 bool TextField::OnKeyEvent( const KeyEvent& event )
 {
-  if( Dali::DALI_KEY_ESCAPE == event.keyCode )
+  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
   {
     ClearKeyInputFocus();
+    return true;
   }
 
   return mController->KeyEvent( event );
@@ -817,24 +999,56 @@ 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", mController.Get(), imfEvent.eventName );
+
+  bool update( false );
+
+  std::string text;
+  unsigned int cursorPosition( 0 );
+
   switch ( imfEvent.eventName )
   {
     case ImfManager::COMMIT:
     {
-      KeyEvent event( "", imfEvent.predictiveString, 0, 0, 0, KeyEvent::Down );
-      mController->KeyEvent( event );
+      mController->InsertText( imfEvent.predictiveString, Text::Controller::COMMIT );
+      break;
+    }
+    case ImfManager::PREEDIT:
+    {
+      mController->InsertText( imfEvent.predictiveString, Text::Controller::PRE_EDIT );
+      update = true;
       break;
     }
-    case ImfManager::PREEDIT: // fall through
     case ImfManager::DELETESURROUNDING:
+    {
+      mController->RemoveText( imfEvent.cursorOffset, imfEvent.numberOfChars );
+      break;
+    }
     case ImfManager::GETSURROUNDING:
+    {
+      mController->GetText( text );
+      cursorPosition = mController->GetLogicalCursorPosition();
+
+      imfManager.SetSurroundingText( text );
+      imfManager.SetCursorPosition( cursorPosition );
+      break;
+    }
     case ImfManager::VOID:
     {
       // do nothing
+      break;
     }
   } // end switch
 
-  return ImfManager::ImfCallbackData();
+  if( ImfManager::GETSURROUNDING != imfEvent.eventName )
+  {
+    mController->GetText( text );
+    cursorPosition = mController->GetLogicalCursorPosition();
+  }
+
+  ImfManager::ImfCallbackData callbackData( update, cursorPosition, text, false );
+
+  return callbackData;
 }
 
 void TextField::RequestTextRelayout()
@@ -842,6 +1056,12 @@ void TextField::RequestTextRelayout()
   RelayoutRequest();
 }
 
+void TextField::MaxLengthReached()
+{
+  Dali::Toolkit::TextField handle( GetOwner() );
+  mMaxLengthReachedSignal.Emit( handle );
+}
+
 void TextField::EnableClipping( bool clipping, const Vector2& size )
 {
   if( clipping )
@@ -872,6 +1092,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", mController.Get(), keyboardShown );
+
   // Just hide the grab handle when keyboard is hidden.
   if (!keyboardShown )
   {