Changed styles to use case-insensitive matching
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / builder / builder-impl.cpp
index ea0b15a..de3fbe1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 // EXTERNAL INCLUDES
 #include <sys/stat.h>
 #include <sstream>
+
 #include <dali/public-api/render-tasks/render-task-list.h>
 #include <dali/public-api/object/type-info.h>
 #include <dali/public-api/object/type-registry.h>
 #include <dali/public-api/object/property-array.h>
 #include <dali/public-api/actors/layer.h>
-#include <dali/public-api/actors/image-actor.h>
 #include <dali/public-api/actors/camera-actor.h>
 #include <dali/devel-api/scripting/scripting.h>
 #include <dali/public-api/signals/functor-delegate.h>
 #include <dali-toolkit/internal/builder/builder-get-is.inl.h>
 #include <dali-toolkit/internal/builder/builder-filesystem.h>
 #include <dali-toolkit/internal/builder/builder-declarations.h>
+#include <dali-toolkit/internal/builder/builder-set-property.h>
 #include <dali-toolkit/internal/builder/replacement.h>
+#include <dali-toolkit/internal/builder/tree-node-manipulator.h>
+
+#include <dali-toolkit/internal/builder/builder-impl-debug.h>
 
 namespace Dali
 {
@@ -52,13 +56,8 @@ namespace Internal
 class Replacement;
 
 extern Animation CreateAnimation(const TreeNode& child, const Replacement& replacements, const Dali::Actor searchRoot, Builder* const builder );
-extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value );
-extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value, const Replacement& replacements );
-extern bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value );
-extern bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value, const Replacement& replacements );
 extern Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder);
 extern Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder);
-extern Actor SetupActor( const TreeNode& node, Actor& actor, const Replacement& constant );
 
 #if defined(DEBUG_ENABLED)
 Integration::Log::Filter* gFilterScript  = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_SCRIPT");
@@ -67,6 +66,8 @@ Integration::Log::Filter* gFilterScript  = Integration::Log::Filter::New(Debug::
 namespace
 {
 
+#define TOKEN_STRING(x) #x
+
 const std::string KEYNAME_STYLES    = "styles";
 const std::string KEYNAME_TYPE      = "type";
 const std::string KEYNAME_ACTORS    = "actors";
@@ -74,116 +75,34 @@ const std::string KEYNAME_SIGNALS   = "signals";
 const std::string KEYNAME_NAME      = "name";
 const std::string KEYNAME_TEMPLATES = "templates";
 const std::string KEYNAME_INCLUDES  = "includes";
+const std::string KEYNAME_MAPPINGS  = "mappings";
 
-typedef std::vector<const TreeNode*> TreeNodeList;
-
-template <typename T>
-std::string ToString(const T& value)
-{
-  std::stringstream ss;
-  ss << value;
-  return ss.str();
-}
+const std::string PROPERTIES = "properties";
+const std::string ANIMATABLE_PROPERTIES = "animatableProperties";
 
-template <>
-std::string ToString(const Rect<int>& value)
-{
-  std::stringstream ss;
-  ss << value.x << "," << value.y << "," << value.width << "," << value.height;
-  return ss.str();
-}
+typedef std::vector<const TreeNode*> TreeNodeList;
 
-#if defined(DEBUG_ENABLED)
 
-std::string PropertyValueToString( const Property::Value& value )
+bool GetMappingKey( const std::string& str, std::string& key )
 {
-  std::string ret;
-
-  switch( value.GetType() )
+  bool result = false;
+  std::string test( str );
+  if( ! test.empty() )
   {
-    case Property::NONE:
-    {
-      ret = "NONE";
-      break;
-    }            ///< No type
-    case Property::BOOLEAN:
-    {
-      ret = value.Get<bool>() ? "True" : "False";
-      break;
-    }
-    case Property::FLOAT:
-    {
-
-      ret = ToString( value.Get<float>() );
-      break;
-    }
-    case Property::INTEGER:
-    {
-      ret = ToString( value.Get<int>() );
-      break;
-    }
-    case Property::UNSIGNED_INTEGER:
-    {
-      ret = ToString( value.Get<unsigned int>() );
-      break;
-    }
-    case Property::VECTOR2:
-    {
-      ret = ToString( value.Get<Vector2>() );
-      break;
-    }
-    case Property::VECTOR3:
-    {
-      ret = ToString( value.Get<Vector3>() );
-      break;
-    }
-    case Property::VECTOR4:
-    {
-      ret = ToString( value.Get<Vector4>() );
-      break;
-    }
-    case Property::MATRIX3:
-    {
-      ret = ToString( value.Get<Matrix3>() );
-      break;
-    }
-    case Property::MATRIX:
-    {
-      ret = ToString( value.Get<Matrix>() );
-      break;
-    }
-    case Property::RECTANGLE:
+    if( test.at(0) == '<' )
     {
-      ret = ToString( value.Get< Rect<int> >() );
-      break;
-    }
-    case Property::ROTATION:
-    {
-      break;
-    }
-    case Property::STRING:
-    {
-      ret = value.Get<std::string>();
-      break;
-    }
-    case Property::ARRAY:
-    {
-      ret = std::string("Array Size=") + ToString( value.Get<Property::Array>().Size() );
-      break;
-    }
-    case Property::MAP:
-    {
-      ret = std::string("Map Size=") + ToString( value.Get<Property::Map>().Count() );
-      break;
+      if( test.at(test.length()-1) == '>' )
+      {
+        key = test.substr( 1, test.length()-2 );
+        result = true;
+      }
     }
   }
-
-  return ret;
+  return result;
 }
-#endif // DEBUG_ENABLED
 
 /*
- * Recursively collects all stylesin a node (An array of style names).
+ * Recursively collects all styles in a node (An array of style names).
  *
  * stylesCollection The set of styles from the json file (a json object of named styles)
  * style The style array to begin the collection from
@@ -198,7 +117,7 @@ void CollectAllStyles( const TreeNode& stylesCollection, const TreeNode& style,
     {
       if( OptionalString styleName = IsString( (*iter).second ) )
       {
-        if( OptionalChild node = IsChild( stylesCollection, *styleName) )
+        if( OptionalChild node = IsChildIgnoreCase( stylesCollection, *styleName) )
         {
           styleList.push_back( &(*node) );
 
@@ -222,6 +141,7 @@ void Builder::SetProperties( const TreeNode& node, Handle& handle, const Replace
 {
   if( handle )
   {
+
     for( TreeNode::ConstIterator iter = node.CBegin(); iter != node.CEnd(); ++iter )
     {
       const TreeNode::KeyNodePair& keyChild = *iter;
@@ -229,85 +149,42 @@ void Builder::SetProperties( const TreeNode& node, Handle& handle, const Replace
       std::string key( keyChild.first );
 
       // ignore special fields; type,actors,signals,styles
-      if(key == KEYNAME_TYPE || key == KEYNAME_ACTORS || key == KEYNAME_SIGNALS || key == KEYNAME_STYLES)
+      if(key == KEYNAME_TYPE || key == KEYNAME_ACTORS || key == KEYNAME_SIGNALS || key == KEYNAME_STYLES || key == KEYNAME_MAPPINGS )
       {
         continue;
       }
 
-      // special field 'image' usually contains an json object description
-      // although sometimes refers to a framebuffer
-      if( 0 == keyChild.second.Size() )
-      {
-        if(key == "image")
-        {
-          ImageActor imageActor = ImageActor::DownCast(handle);
-          if(imageActor)
-          {
-            if( OptionalString s = constant.IsString( keyChild.second ) )
-            {
-              FrameBufferImage fb = GetFrameBufferImage(*s, constant);
-              if(fb)
-              {
-                imageActor.SetImage( fb );
-              }
-            }
-          }
-        }
-      }
-
-      // special field 'effect' references the shader effect instances
-      if(key == "effect")
-      {
-        RenderableActor actor = RenderableActor::DownCast(handle);
-        if( actor )
-        {
-          OptionalString str = constant.IsString( keyChild.second );
-          if( str )
-          {
-            ShaderEffect effect = GetShaderEffect( *str, constant );
-            actor.SetShaderEffect(effect);
-          }
-        }
-        else
-        {
-          DALI_SCRIPT_WARNING("Could not find or set shader effect\n");
-        }
-
-        continue;
-      }
-
       Handle propertyObject( handle );
 
       Dali::Property::Index index = propertyObject.GetPropertyIndex( key );
 
-      if( Property::INVALID_INDEX == index )
+      if( Property::INVALID_INDEX != index )
       {
-        RenderableActor actor = RenderableActor::DownCast(handle);
-        if( actor )
+        Property::Type type = propertyObject.GetPropertyType(index);
+        Property::Value value;
+        bool mapped = false;
+
+        // if node.value is a mapping, get the property value from the "mappings" table
+        if( keyChild.second.GetType() == TreeNode::STRING )
         {
-          if( ShaderEffect effect = actor.GetShaderEffect() )
+          std::string mappingKey;
+          if( GetMappingKey(keyChild.second.GetString(), mappingKey) )
           {
-            index = effect.GetPropertyIndex( key );
-            if(index != Property::INVALID_INDEX)
-            {
-              propertyObject = effect;
-            }
+            OptionalChild mappingRoot = IsChild( mParser.GetRoot(), KEYNAME_MAPPINGS );
+            mapped = GetPropertyMap( *mappingRoot, mappingKey.c_str(), type, value );
           }
         }
-      }
-
-      if( Property::INVALID_INDEX != index )
-      {
-        Property::Type type = propertyObject.GetPropertyType(index);
-
-        Property::Value value;
-        if( !SetPropertyFromNode( keyChild.second, type, value, constant ) )
+        if( ! mapped )
         {
-          // verbose as this might not be a problem
-          // eg parent-origin can be a string which is picked up later
-          DALI_SCRIPT_VERBOSE("Could not convert property:%s\n", key.c_str());
+          mapped = DeterminePropertyFromNode( keyChild.second, type, value, constant );
+          if( ! mapped )
+          {
+            // Just determine the property from the node and if it's valid, let the property object handle it
+            DeterminePropertyFromNode( keyChild.second, value, constant );
+            mapped = ( value.GetType() != Property::NONE );
+          }
         }
-        else
+        if( mapped )
         {
           DALI_SCRIPT_VERBOSE("SetProperty '%s' Index=:%d Value Type=%d Value '%s'\n", key.c_str(), index, value.GetType(), PropertyValueToString(value).c_str() );
 
@@ -319,6 +196,10 @@ void Builder::SetProperties( const TreeNode& node, Handle& handle, const Replace
         DALI_SCRIPT_VERBOSE("SetProperty INVALID '%s' Index=:%d\n", key.c_str(), index);
       }
 
+      // Add custom properties
+      SetCustomProperties(node, handle, constant, PROPERTIES, Property::READ_WRITE);
+      SetCustomProperties(node, handle, constant, ANIMATABLE_PROPERTIES, Property::ANIMATABLE);
+
     } // for property nodes
   }
   else
@@ -327,6 +208,27 @@ void Builder::SetProperties( const TreeNode& node, Handle& handle, const Replace
   }
 }
 
+void Builder::SetCustomProperties( const TreeNode& node, Handle& handle, const Replacement& constant,
+                          const std::string& childName, Property::AccessMode accessMode )
+{
+  // Add custom properties
+  if( OptionalChild customPropertiesChild = IsChild(node, childName) )
+  {
+    const TreeNode& customPropertiesNode = *customPropertiesChild;
+    const TreeConstIter endIter = customPropertiesNode.CEnd();
+    for( TreeConstIter iter = customPropertiesNode.CBegin(); endIter != iter; ++iter )
+    {
+      const TreeNode::KeyNodePair& keyChild = *iter;
+      std::string key( keyChild.first );
+
+      Property::Value value;
+      DeterminePropertyFromNode( keyChild.second, value, constant );
+      // Register/Set property.
+      handle.RegisterProperty( key, value, accessMode );
+    }
+  }
+}
+
 // Set properties from node on handle.
 void Builder::ApplyProperties( const TreeNode& root, const TreeNode& node,
                                Dali::Handle& handle, const Replacement& constant )
@@ -337,8 +239,6 @@ void Builder::ApplyProperties( const TreeNode& root, const TreeNode& node,
 
     if( actor )
     {
-      SetupActor( node, actor, constant );
-
       // add signals
       SetupSignalAction( mSlotDelegate.GetConnectionTracker(), root, node, actor, this );
       SetupPropertyNotification( mSlotDelegate.GetConnectionTracker(), root, node, actor, this );
@@ -550,7 +450,7 @@ void Builder::SetupTask( RenderTask& task, const TreeNode& node, const Replaceme
   const Stage& stage = Stage::GetCurrent();
   Layer root  = stage.GetRootLayer();
 
-  if( OptionalString s = constant.IsString( IsChild(node, "source-actor") ) )
+  if( OptionalString s = constant.IsString( IsChild(node, "sourceActor") ) )
   {
     Actor actor = root.FindChildByName(*s);
     if(actor)
@@ -563,7 +463,7 @@ void Builder::SetupTask( RenderTask& task, const TreeNode& node, const Replaceme
     }
   }
 
-  if( OptionalString s = constant.IsString( IsChild(node, "camera-actor") ) )
+  if( OptionalString s = constant.IsString( IsChild(node, "cameraActor") ) )
   {
     CameraActor actor = CameraActor::DownCast( root.FindChildByName(*s) );
     if(actor)
@@ -576,7 +476,7 @@ void Builder::SetupTask( RenderTask& task, const TreeNode& node, const Replaceme
     }
   }
 
-  if( OptionalString s = constant.IsString( IsChild(node, "target-frame-buffer") ) )
+  if( OptionalString s = constant.IsString( IsChild(node, "targetFrameBuffer") ) )
   {
     FrameBufferImage fb = GetFrameBufferImage( *s, constant );
     if(fb)
@@ -589,7 +489,7 @@ void Builder::SetupTask( RenderTask& task, const TreeNode& node, const Replaceme
     }
   }
 
-  if( OptionalString s = constant.IsString( IsChild(node, "screen-to-frame-buffer-function") ) )
+  if( OptionalString s = constant.IsString( IsChild(node, "screenToFrameBufferFunction") ) )
   {
     if("DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION" == *s)
     {
@@ -606,8 +506,7 @@ void Builder::SetupTask( RenderTask& task, const TreeNode& node, const Replaceme
   }
 
   // other setup is via the property system
-  SetProperties( node, task, constant ); // @ todo, remove 'source-actor', 'camera-actor'?
-
+  SetProperties( node, task, constant );
 }
 
 void Builder::CreateRenderTask( const std::string &name )
@@ -618,7 +517,7 @@ void Builder::CreateRenderTask( const std::string &name )
 
   const Stage& stage = Stage::GetCurrent();
 
-  OptionalChild tasks = IsChild(*mParser.GetRoot(), "render-tasks");
+  OptionalChild tasks = IsChild(*mParser.GetRoot(), "renderTasks");
 
   if(tasks)
   {
@@ -657,42 +556,6 @@ void Builder::CreateRenderTask( const std::string &name )
   }
 }
 
-ShaderEffect Builder::GetShaderEffect( const std::string &name)
-{
-  Replacement constant( mReplacementMap );
-  return GetShaderEffect( name, constant );
-}
-
-ShaderEffect Builder::GetShaderEffect( const std::string &name, const Replacement& constant )
-{
-  DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
-
-  ShaderEffect ret;
-
-  ShaderEffectLut::const_iterator iter( mShaderEffectLut.find( name ) );
-  if( iter != mShaderEffectLut.end() )
-  {
-    ret = iter->second;
-  }
-  else
-  {
-    if( OptionalChild effects = IsChild( *mParser.GetRoot(), "shader-effects") )
-    {
-      if( OptionalChild effect = IsChild( *effects, name ) )
-      {
-        Dali::Property::Value propertyMap(Property::MAP);
-        if( SetPropertyFromNode( *effect, Property::MAP, propertyMap, constant ) )
-        {
-          ret = Dali::Scripting::NewShaderEffect( propertyMap );
-          mShaderEffectLut[ name ] = ret;
-        }
-      }
-    }
-  }
-
-  return ret;
-}
-
 FrameBufferImage Builder::GetFrameBufferImage( const std::string &name )
 {
   Replacement constant( mReplacementMap );
@@ -712,17 +575,21 @@ FrameBufferImage Builder::GetFrameBufferImage( const std::string &name, const Re
   }
   else
   {
-    if( OptionalChild images = IsChild( *mParser.GetRoot(), "frame-buffer-images") )
+    if( OptionalChild images = IsChild( *mParser.GetRoot(), "frameBufferImages") )
     {
       if( OptionalChild image = IsChild( *images, name ) )
       {
         Dali::Property::Value property(Property::MAP);
-        if( SetPropertyFromNode( *image, Property::MAP, property, constant ) )
+        if( DeterminePropertyFromNode( *image, Property::MAP, property, constant ) )
         {
           Property::Map* map = property.GetMap();
-          (*map)[ KEYNAME_TYPE ] = Property::Value(std::string("FrameBufferImage") );
-          ret = FrameBufferImage::DownCast( Dali::Scripting::NewImage( property ) );
-          mFrameBufferImageLut[ name ] = ret;
+
+          if( map )
+          {
+            (*map)[ KEYNAME_TYPE ] = Property::Value(std::string("FrameBufferImage") );
+            ret = FrameBufferImage::DownCast( Dali::Scripting::NewImage( property ) );
+            mFrameBufferImageLut[ name ] = ret;
+          }
         }
       }
     }
@@ -752,16 +619,16 @@ Path Builder::GetPath( const std::string& name )
         if( OptionalChild pointsProperty = IsChild( *path, "points") )
         {
           Dali::Property::Value points(Property::ARRAY);
-          if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
+          if( DeterminePropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
           {
             ret = Path::New();
             ret.SetProperty( Path::Property::POINTS, points);
 
-            //control-points property
-            if( OptionalChild pointsProperty = IsChild( *path, "control-points") )
+            //controlPoints property
+            if( OptionalChild pointsProperty = IsChild( *path, "controlPoints") )
             {
               Dali::Property::Value points(Property::ARRAY);
-              if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
+              if( DeterminePropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
               {
                 ret.SetProperty( Path::Property::CONTROL_POINTS, points);
               }
@@ -826,16 +693,16 @@ PathConstrainer Builder::GetPathConstrainer( const std::string& name )
         if( OptionalChild pointsProperty = IsChild( *pathConstrainer, "points") )
         {
           Dali::Property::Value points(Property::ARRAY);
-          if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
+          if( DeterminePropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
           {
             ret = PathConstrainer::New();
             ret.SetProperty( PathConstrainer::Property::POINTS, points);
 
-            //control-points property
-            if( OptionalChild pointsProperty = IsChild( *pathConstrainer, "control-points") )
+            //controlPoints property
+            if( OptionalChild pointsProperty = IsChild( *pathConstrainer, "controlPoints") )
             {
               Dali::Property::Value points(Property::ARRAY);
-              if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
+              if( DeterminePropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
               {
                 ret.SetProperty( PathConstrainer::Property::CONTROL_POINTS, points);
               }
@@ -935,16 +802,16 @@ Dali::LinearConstrainer Builder::GetLinearConstrainer( const std::string& name )
         if( OptionalChild pointsProperty = IsChild( *linearConstrainer, "value") )
         {
           Dali::Property::Value points(Property::ARRAY);
-          if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
+          if( DeterminePropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
           {
             ret = Dali::LinearConstrainer::New();
             ret.SetProperty( LinearConstrainer::Property::VALUE, points);
 
-            //control-points property
+            //controlPoints property
             if( OptionalChild pointsProperty = IsChild( *linearConstrainer, "progress") )
             {
               Dali::Property::Value points(Property::ARRAY);
-              if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
+              if( DeterminePropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
               {
                 ret.SetProperty( LinearConstrainer::Property::PROGRESS, points);
               }
@@ -972,7 +839,7 @@ Dali::LinearConstrainer Builder::GetLinearConstrainer( const std::string& name )
 
 bool Builder::IsLinearConstrainer( const std::string& name )
 {
-  //Search the LinearConstrainer in the LUT
+  // Search the LinearConstrainer in the LUT
   size_t count( mLinearConstrainerLut.size() );
   for( size_t i(0); i!=count; ++i )
   {
@@ -1042,7 +909,7 @@ void Builder::AddActors( const std::string &sectionName, Actor toActor )
     // to add automatically
     if( "stage" == sectionName )
     {
-      if( OptionalChild renderTasks = IsChild(*mParser.GetRoot(), "render-tasks") )
+      if( OptionalChild renderTasks = IsChild(*mParser.GetRoot(), "renderTasks") )
       {
         if( OptionalChild tasks = IsChild(*renderTasks, "stage") )
         {
@@ -1104,6 +971,124 @@ Animation Builder::CreateAnimation( const std::string& animationName )
   return CreateAnimation( animationName, replacement, Dali::Stage::GetCurrent().GetRootLayer() );
 }
 
+bool Builder::ConvertChildValue( const TreeNode& mappingRoot, KeyStack& keyStack, Property::Value& child )
+{
+  bool result = false;
+
+  switch( child.GetType() )
+  {
+    case Property::STRING:
+    {
+      std::string value;
+      if( child.Get( value ) )
+      {
+        std::string key;
+        if( GetMappingKey( value, key ) )
+        {
+          // Check key for cycles:
+          result=true;
+          for( KeyStack::iterator iter = keyStack.begin() ; iter != keyStack.end(); ++iter )
+          {
+            if( key.compare(*iter) == 0 )
+            {
+              // key is already in stack; stop.
+              DALI_LOG_WARNING("Detected cycle in stylesheet mapping table:%s\n", key.c_str());
+              child = Property::Value("");
+              result=false;
+              break;
+            }
+          }
+
+          if( result )
+          {
+            // The following call will overwrite the child with the value
+            // from the mapping.
+            RecursePropertyMap( mappingRoot, keyStack, key.c_str(), Property::NONE, child );
+            result = true;
+          }
+        }
+      }
+      break;
+    }
+
+    case Property::MAP:
+    {
+      Property::Map* map = child.GetMap();
+      if( map )
+      {
+        for( Property::Map::SizeType i=0; i < map->Count(); ++i )
+        {
+          Property::Value& child = map->GetValue(i);
+          ConvertChildValue(mappingRoot, keyStack, child);
+        }
+      }
+      break;
+    }
+
+    case Property::ARRAY:
+    {
+      Property::Array* array = child.GetArray();
+      if( array )
+      {
+        for( Property::Array::SizeType i=0; i < array->Count(); ++i )
+        {
+          Property::Value& child = array->GetElementAt(i);
+          ConvertChildValue(mappingRoot, keyStack, child);
+        }
+      }
+      break;
+    }
+
+    default:
+      // Ignore other types.
+      break;
+  }
+
+  return result;
+}
+
+bool Builder::RecursePropertyMap( const TreeNode& mappingRoot, KeyStack& keyStack, const char* theKey, Property::Type propertyType, Property::Value& value )
+{
+  Replacement replacer( mReplacementMap );
+  bool result = false;
+
+  keyStack.push_back( theKey );
+
+  for( TreeNode::ConstIterator iter = mappingRoot.CBegin(); iter != mappingRoot.CEnd(); ++iter )
+  {
+    std::string aKey( (*iter).first );
+    if( aKey.compare( theKey ) == 0 )
+    {
+      if( propertyType == Property::NONE )
+      {
+        DeterminePropertyFromNode( (*iter).second, value, replacer );
+        result = true;
+      }
+      else
+      {
+        result = DeterminePropertyFromNode( (*iter).second, propertyType, value, replacer );
+      }
+
+      if( result )
+      {
+        ConvertChildValue(mappingRoot, keyStack, value);
+      }
+      break;
+    }
+  }
+  keyStack.pop_back();
+
+  return result;
+}
+
+
+bool Builder::GetPropertyMap( const TreeNode& mappingRoot, const char* theKey, Property::Type propertyType, Property::Value& value )
+{
+  KeyStack keyStack;
+  return RecursePropertyMap( mappingRoot, keyStack, theKey, propertyType, value );
+}
+
+
 void Builder::LoadFromString( std::string const& data, Dali::Toolkit::Builder::UIFormat format )
 {
   // parser to get constants and includes only
@@ -1117,7 +1102,6 @@ void Builder::LoadFromString( std::string const& data, Dali::Toolkit::Builder::U
                       parser.GetErrorDescription().c_str() );
 
     DALI_ASSERT_ALWAYS(!"Cannot parse JSON");
-
   }
   else
   {
@@ -1154,8 +1138,10 @@ void Builder::LoadFromString( std::string const& data, Dali::Toolkit::Builder::U
     }
   }
 
-  DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Cannot parse JSON");
+  DUMP_PARSE_TREE(parser); // This macro only writes out if DEBUG is enabled and the "DUMP_TREE" constant is defined in the stylesheet.
+  DUMP_TEST_MAPPINGS(parser);
 
+  DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Cannot parse JSON");
 }
 
 void Builder::AddConstants( const Property::Map& map )
@@ -1202,15 +1188,8 @@ void Builder::LoadConstants( const TreeNode& root, Property::Map& intoMap )
 #if defined(DEBUG_ENABLED)
         DALI_SCRIPT_VERBOSE("Constant set from json '%s'\n", (*iter).second.GetName());
 #endif
-        if( SetPropertyFromNode( (*iter).second, property, replacer ) )
-        {
-          intoMap[ (*iter).second.GetName() ] = property;
-        }
-        else
-        {
-          DALI_SCRIPT_WARNING("Cannot convert property for constant %s\n",
-                              (*iter).second.GetName() == NULL ? "no name?" : (*iter).second.GetName());
-        }
+        DeterminePropertyFromNode( (*iter).second, property, replacer );
+        intoMap[ (*iter).second.GetName() ] = property;
       }
     }
   }
@@ -1252,7 +1231,9 @@ bool Builder::ApplyStyle( const std::string& styleName, Handle& handle, const Re
   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
 
   OptionalChild styles = IsChild( *mParser.GetRoot(), KEYNAME_STYLES );
-  OptionalChild style  = IsChild( *styles, styleName );
+
+  std::string styleNameLower(styleName);
+  OptionalChild style  = IsChildIgnoreCase( *styles, styleNameLower );
 
   if( styles && style )
   {
@@ -1357,6 +1338,14 @@ Builder::Builder()
 : mSlotDelegate( this )
 {
   mParser = Dali::Toolkit::JsonParser::New();
+
+  Property::Map defaultDirs;
+  defaultDirs[ TOKEN_STRING(DALI_IMAGE_DIR) ]       = DALI_IMAGE_DIR;
+  defaultDirs[ TOKEN_STRING(DALI_SOUND_DIR) ]       = DALI_SOUND_DIR;
+  defaultDirs[ TOKEN_STRING(DALI_STYLE_DIR) ]       = DALI_STYLE_DIR;
+  defaultDirs[ TOKEN_STRING(DALI_STYLE_IMAGE_DIR) ] = DALI_STYLE_IMAGE_DIR;
+
+  AddConstants( defaultDirs );
 }
 
 Builder::~Builder()