} \
");
+ std::string JSON_CONSTANTS("\
+{ \
+ 'constants': \
+ { \
+ 'HELLO':'Hello World', \
+ 'HELLO2':'Hello {WORLD}' \
+ }, \
+ 'styles': \
+ { \
+ 'basic-text': { \
+ 'type':'TextActor', \
+ 'text':'{HELLO2}' \
+ } \
+ }, \
+ 'animations': \
+ { \
+ 'rotate': \
+ { \
+ 'duration': 10, \
+ 'properties': \
+ [ \
+ { \
+ 'actor':'{ACTOR}', \
+ 'property':'rotation', \
+ 'value':[0, 3, 0, 0], \
+ 'alpha-function': 'EASE_IN_OUT', \
+ 'time-period': {'delay': 0, 'duration': 3 } \
+ } \
+ ] \
+ } \
+ }, \
+ 'stage': \
+ [ \
+ {'name':'txt1', \
+ 'type':'TextActor', \
+ 'text':'{HELLO}' \
+ } \
+ ] \
+} \
+");
+
std::string ReplaceQuotes(const std::string &in_s)
{
void (*tet_cleanup)() = Cleanup;
}
+static void UtcDaliBuilderConstants();
static void UtcDaliBuilderTextActorCreateFromStyle();
static void UtcDaliBuilderTextActorCreateAnimation();
static void UtcDaliBuilderTextActorApplyFromStyle();
NEGATIVE_TC_IDX,
};
-// Add test functionality for all APIs in the class (Positive and Negative)
+#define MAX_NUMBER_OF_TESTS 10000
extern "C" {
- struct tet_testlist tet_testlist[] = {
- { UtcDaliBuilderTextActorCreateFromStyle, POSITIVE_TC_IDX },
- { UtcDaliBuilderTextActorCreateAnimation, POSITIVE_TC_IDX },
- { UtcDaliBuilderTextActorApplyFromStyle, POSITIVE_TC_IDX },
- { UtcDaliBuilderStyles, POSITIVE_TC_IDX },
- { UtcDaliBuilderAddActorsOther, POSITIVE_TC_IDX },
- { UtcDaliBuilderAddActors, POSITIVE_TC_IDX },
- { UtcDaliBuilderSetProperty, POSITIVE_TC_IDX },
- { NULL, 0 }
- };
+ struct tet_testlist tet_testlist[MAX_NUMBER_OF_TESTS];
}
+TEST_FUNCTION( UtcDaliBuilderConstants , POSITIVE_TC_IDX );
+TEST_FUNCTION( UtcDaliBuilderTextActorCreateFromStyle , POSITIVE_TC_IDX );
+TEST_FUNCTION( UtcDaliBuilderTextActorCreateAnimation , POSITIVE_TC_IDX );
+TEST_FUNCTION( UtcDaliBuilderTextActorApplyFromStyle , POSITIVE_TC_IDX );
+TEST_FUNCTION( UtcDaliBuilderStyles , POSITIVE_TC_IDX );
+TEST_FUNCTION( UtcDaliBuilderAddActorsOther , POSITIVE_TC_IDX );
+TEST_FUNCTION( UtcDaliBuilderAddActors , POSITIVE_TC_IDX );
+TEST_FUNCTION( UtcDaliBuilderSetProperty , POSITIVE_TC_IDX );
+
// Called only once before first test is run.
static void Startup()
{
{
}
+static void UtcDaliBuilderConstants()
+{
+ ToolkitTestApplication application;
+ Stage stage = Stage::GetCurrent();
+
+ tet_infoline(" UtcDaliBuilderConstants");
+
+ Builder builder = Builder::New();
+
+ PropertyValueMap userMap;
+ userMap["WORLD"] = "World";
+ builder.AddConstants(userMap);
+
+ builder.LoadFromString( ReplaceQuotes(JSON_CONSTANTS) );
+
+ // constants in json
+ Layer layer = stage.GetRootLayer();
+ size_t count = layer.GetChildCount();
+
+ builder.AddActors( layer );
+ DALI_TEST_CHECK( layer.GetChildCount() == count + 1 );
+
+ TextActor actor = TextActor::DownCast( layer.GetChildAt( count ) );
+ DALI_TEST_CHECK( actor );
+ DALI_TEST_CHECK( actor.GetText() == std::string("Hello World") );
+
+ // global constants
+ PropertyValueMap map;
+ map["HELLO2"] = "Hi";
+
+ builder.AddConstants( map );
+
+ actor = TextActor::DownCast( builder.CreateFromStyle("basic-text") );
+ DALI_TEST_CHECK( actor );
+ DALI_TEST_CHECK( actor.GetText() == std::string("Hi") );
+
+ // user overriding
+ userMap["HELLO2"] = "Hello Dali";
+ actor = TextActor::DownCast( builder.CreateFromStyle("basic-text", userMap) );
+ DALI_TEST_CHECK( actor );
+ DALI_TEST_CHECK( actor.GetText() == std::string("Hello Dali") );
+
+ // animation constants
+ actor = TextActor::DownCast( layer.GetChildAt( count ) );
+ actor.SetName("rotate-me");
+ userMap["ACTOR"] = actor.GetName();
+
+ Animation anim = builder.CreateAnimation("rotate", userMap);
+ DALI_TEST_CHECK( anim );
+ DALI_TEST_CHECK( 10.0f == anim.GetDuration() );
+
+}
+
static void UtcDaliBuilderTextActorCreateFromStyle()
{
ToolkitTestApplication application;
// INTERNAL INCLUDES
#include <dali-toolkit/internal/builder/builder-impl.h>
#include <dali-toolkit/internal/builder/builder-get-is.inl.h>
+#include <dali-toolkit/internal/builder/replacement.h>
namespace // unnamed namespace
{
using namespace Dali;
-TimePeriod GetTimePeriod( const TreeNode& child )
+TimePeriod GetTimePeriod( const TreeNode& child, const Toolkit::Internal::Replacement& constant )
{
- OptionalFloat delay = IsFloat( IsChild(child, "delay" ) );
- OptionalFloat duration = IsFloat( IsChild(child, "duration" ) );
+ OptionalFloat delay = constant.IsFloat( IsChild(child, "delay" ) );
+ OptionalFloat duration = constant.IsFloat( IsChild(child, "duration" ) );
DALI_ASSERT_ALWAYS( duration && "Time period must have at least a duration" );
if( delay )
namespace Internal
{
-Animation CreateAnimation( const TreeNode& child )
+Animation CreateAnimation( const TreeNode& child, const Replacement& constant, Dali::Actor searchRoot )
{
float durationSum = 0.f;
+ Dali::Actor searchActor = searchRoot ? searchRoot : Dali::Stage::GetCurrent().GetRootLayer();
+
Animation animation( Animation::New( 0.f ) );
- if( OptionalBoolean looping = IsBoolean( IsChild(child, "loop" ) ) )
+ // duration needs to be set before AnimateTo calls for correct operation when AnimateTo has no "time-period".
+ OptionalFloat duration = constant.IsFloat( IsChild(child, "duration" ) );
+
+ if( duration )
+ {
+ animation.SetDuration( *duration );
+ }
+ else
+ {
+ animation.SetDuration( durationSum );
+ }
+
+ if( OptionalBoolean looping = constant.IsBoolean( IsChild(child, "loop" ) ) )
{
animation.SetLooping( *looping );
}
- if( OptionalString endAction = IsString( IsChild(child, "end-action" ) ) )
+ if( OptionalString endAction = constant.IsString( IsChild(child, "end-action" ) ) )
{
if("BAKE" == *endAction)
{
}
}
- if( OptionalString endAction = IsString( IsChild(child, "destroy-action" ) ) )
+ if( OptionalString endAction = constant.IsString( IsChild(child, "destroy-action" ) ) )
{
if("BAKE" == *endAction)
{
{
const TreeNode::KeyNodePair& pKeyChild = *iter;
- OptionalString actorName( IsString( pKeyChild.second, "actor" ) );
- OptionalString property( IsString( pKeyChild.second, "property" ) );
+ OptionalString actorName( constant.IsString( IsChild(pKeyChild.second, "actor" ) ) );
+ OptionalString property( constant.IsString( IsChild(pKeyChild.second, "property" ) ) );
DALI_ASSERT_ALWAYS( actorName && "Animation must specify actor name" );
DALI_ASSERT_ALWAYS( property && "Animation must specify a property name" );
- Actor targetActor = Stage::GetCurrent().GetRootLayer().FindChildByName( *actorName );
+ Actor targetActor = searchActor.FindChildByName( *actorName );
DALI_ASSERT_ALWAYS( targetActor && "Actor must exist for property" );
Property::Index idx( targetActor.GetPropertyIndex( *property ) );
AlphaFunction alphaFunction( AlphaFunctions::Default );
TimePeriod timePeriod( 0.f );
- if( OptionalChild timeChild = IsChild( pKeyChild.second, "time-period" ) )
+ OptionalChild timeChild = IsChild( pKeyChild.second, "time-period" );
+
+ if( timeChild )
{
- timePeriod = GetTimePeriod( *timeChild );
+ timePeriod = GetTimePeriod( *timeChild, constant );
}
durationSum = std::max( durationSum, timePeriod.delaySeconds + timePeriod.durationSeconds );
- if( OptionalString alphaChild = IsString( pKeyChild.second, "alpha-function" ) )
+ if( OptionalString alphaChild = constant.IsString( IsChild(pKeyChild.second, "alpha-function" ) ) )
{
alphaFunction = GetAlphaFunction( *alphaChild );
}
{
const TreeNode::KeyNodePair& kfKeyChild = *iter;
- OptionalFloat kfProgress = IsFloat( kfKeyChild.second, "progress" );
+ OptionalFloat kfProgress = constant.IsFloat( IsChild(kfKeyChild.second, "progress" ) );
DALI_ASSERT_ALWAYS( kfProgress && "Key frame entry must have 'progress'" );
OptionalChild kfValue = IsChild( kfKeyChild.second, "value" );
}
AlphaFunction kfAlphaFunction( AlphaFunctions::Default );
- if( OptionalString alphaFuncStr = IsString( pKeyChild.second, "alpha-function") )
+ if( OptionalString alphaFuncStr = constant.IsString( IsChild(pKeyChild.second, "alpha-function") ) )
{
kfAlphaFunction = GetAlphaFunction( *alphaFuncStr );
}
keyframes.Add( *kfProgress, propValue, kfAlphaFunction );
}
- animation.AnimateBetween( prop, keyframes, alphaFunction, timePeriod );
+ if( timeChild )
+ {
+ animation.AnimateBetween( prop, keyframes, alphaFunction, timePeriod );
+ }
+ else
+ {
+ animation.AnimateBetween( prop, keyframes, alphaFunction );
+ }
}
else
{
throw;
}
- if( OptionalBoolean relative = IsBoolean(pKeyChild.second, "relative") )
+ if( OptionalBoolean relative = constant.IsBoolean( IsChild(pKeyChild.second, "relative") ) )
{
- animation.AnimateBy( prop, propValue, alphaFunction, timePeriod );
+ if( timeChild )
+ {
+ animation.AnimateBy( prop, propValue, alphaFunction, timePeriod );
+ }
+ else
+ {
+ animation.AnimateBy( prop, propValue, alphaFunction );
+ }
}
else
{
- animation.AnimateTo( prop, propValue, alphaFunction, timePeriod );
+ if( timeChild )
+ {
+ animation.AnimateTo( prop, propValue, alphaFunction, timePeriod );
+ }
+ else
+ {
+ animation.AnimateTo( prop, propValue, alphaFunction );
+ }
}
}
}
}
- if( OptionalFloat duration = IsFloat( child, "duration" ) )
- {
- animation.SetDuration( *duration );
- }
- else
- {
- animation.SetDuration( durationSum );
- }
-
return animation;
}
+Animation CreateAnimation( const TreeNode& child )
+{
+ Replacement replacement;
+ return CreateAnimation( child, replacement, Stage::GetCurrent().GetRootLayer() );
+}
+
} // namespace Internal
} // namespace Toolkit
#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/replacement.h>
namespace Dali
{
namespace Internal
{
+class Replacement;
-extern Animation CreateAnimation(const TreeNode& child);
+extern Animation CreateAnimation(const TreeNode& child, const Replacement& replacements, const Dali::Actor searchRoot );
+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);
extern Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor);
extern Actor SetupActor( const TreeNode& node, Actor& actor );
typedef std::vector<const TreeNode*> TreeNodeList;
+template <typename T>
+std::string ToString(const T& value)
+{
+ std::stringstream ss;
+ ss << value;
+ return ss.str();
+}
+
+template <>
+std::string ToString(const Rect<int>& value)
+{
+ std::stringstream ss;
+ ss << value.x << "," << value.y << "," << value.width << "," << value.height;
+ return ss.str();
+}
+
+
+std::string PropertyValueToString( const Property::Value& value )
+{
+ std::string ret;
+
+ switch( value.GetType() )
+ {
+ 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:
+ {
+ 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>().size() );
+ break;
+ }
+ case Property::TYPE_COUNT:
+ {
+ ret = "";
+ break;
+ }
+ }
+
+ return ret;
+}
+
/*
* Sets the handle properties found in the tree node
*/
-void SetProperties( const TreeNode& node, Handle& handle, Builder& builder )
+void SetProperties( const TreeNode& node, Handle& handle, Builder& builder, const Replacement& constant )
{
if( handle )
{
ImageActor imageActor = ImageActor::DownCast(handle);
if(imageActor)
{
- if( OptionalString s = IsString( keyChild.second ) )
+ if( OptionalString s = constant.IsString( keyChild.second ) )
{
- FrameBufferImage fb = builder.GetFrameBufferImage(*s);
+ FrameBufferImage fb = builder.GetFrameBufferImage(*s, constant);
if(fb)
{
imageActor.SetImage( fb );
if(key == "effect")
{
Actor actor = Actor::DownCast(handle);
- OptionalString s = IsString( keyChild.second );
+ OptionalString s = constant.IsString( keyChild.second );
if(actor && s)
{
- ShaderEffect e = builder.GetShaderEffect(*s);
+ ShaderEffect e = builder.GetShaderEffect(*s, constant);
actor.SetShaderEffect(e);
}
else
Property::Type type = handle.GetPropertyType(index);
Property::Value value;
- if( !SetPropertyFromNode( keyChild.second, type, value ) )
+ if( !SetPropertyFromNode( keyChild.second, type, value, constant ) )
{
// verbose as this might not be a problem
// eg parent-origin can be a string which is picked up later
}
else
{
- DALI_SCRIPT_VERBOSE("SetProperty '%s' Index=:%d Value Type=%d\n", key.c_str(), index, value.GetType());
+ DALI_SCRIPT_VERBOSE("SetProperty '%s' Index=:%d Value Type=%d Value '%s'\n", key.c_str(), index, value.GetType(), PropertyValueToString(value).c_str() );
handle.SetProperty( index, value );
}
}
}
+} // namespace anon
+
/*
* Create a dali type from a node.
* If parent given and an actor type was created then add it to the parent and
* recursively add nodes children.
*/
-BaseHandle Create( ConnectionTracker* tracker, const OptionalChild& optionalStyles, const TreeNode& node, const TreeNode& root, Actor parent, Builder& builder )
+BaseHandle Builder::Create( const OptionalChild& optionalStyles, const TreeNode& node, const TreeNode& root, Actor parent,
+ const Replacement& replacements )
{
BaseHandle baseHandle;
TreeNodeList allStyles;
if(!typeInfo)
{
- DALI_SCRIPT_WARNING("Unable to create Dali type from node\n");
+ DALI_SCRIPT_WARNING("Cannot create Dali type from node '%s'\n", node.GetName());
}
else
{
for(TreeNodeList::reverse_iterator iter = allStyles.rbegin(); iter != allStyles.rend(); ++iter)
{
- SetProperties( *(*iter), handle, builder );
+ if( (*iter)->GetType() == TreeNode::ARRAY )
+ {
+ // if its an array then its a list of styles to set to objects already in the hiearchy by name
+ if( actor )
+ {
+ const TreeNode& styleList = *(*iter);
+ for( TreeNode::ConstIterator iterSubStyle = styleList.CBegin(); iterSubStyle != styleList.CEnd(); ++iterSubStyle )
+ {
+ const TreeNode* nameNode = (*iterSubStyle).second.Find("name");
+ if( nameNode && nameNode->GetType() == TreeNode::STRING )
+ {
+ Dali::Actor found = actor.FindChildByName( nameNode->GetString() );
+ if( found )
+ {
+ SetProperties( (*iterSubStyle).second, found, *this, replacements );
+ }
+ else
+ {
+ DALI_SCRIPT_VERBOSE("Cannot find object '%s' in tree to style\n", nameNode->GetString());
+ }
+ }
+ else
+ {
+ DALI_SCRIPT_VERBOSE("Style name is not a string '%s' '%d'\n",
+ nameNode->GetString(), (*iterSubStyle).second.GetType());
+ }
+ }
+ }
+ else
+ {
+ DALI_SCRIPT_VERBOSE("Cannot apply style list to non actor\n");
+ }
+ }
+ else
+ {
+ DALI_ASSERT_DEBUG( (*iter)->GetType() == TreeNode::OBJECT );
+ // else it should be a map of properties
+ SetProperties( *(*iter), handle, *this, replacements );
+ }
- if( actor ) // if we created an actor
+ if( actor )
{
SetupActor( *(*iter), actor);
{
for( TreeConstIter iter = (*actors).CBegin(); iter != (*actors).CEnd(); ++iter )
{
- Create( tracker, optionalStyles, (*iter).second, root, actor, builder );
+ Create( optionalStyles, (*iter).second, root, actor, replacements );
}
}
}
if( actor )
{
// add signals first
- SetupSignalAction( tracker, root, node, actor );
- SetupPropertyNotification( tracker, root, node, actor );
+ SetupSignalAction( mSlotDelegate.GetConnectionTracker(), root, node, actor );
+
+ SetupPropertyNotification( mSlotDelegate.GetConnectionTracker(), root, node, actor );
// then add to parent
if( parent )
}
-} // namespace anon
-
-
ActorContainer Builder::GetTopLevelActors() const
{
// deprecated function.
return Animation();
}
-void Builder::SetupTask( RenderTask& task, const TreeNode& node )
+void Builder::SetupTask( RenderTask& task, const TreeNode& node, const Replacement& constant )
{
const Stage& stage = Stage::GetCurrent();
Layer root = stage.GetRootLayer();
- if( OptionalString s = IsString( IsChild(node, "source-actor") ) )
+ if( OptionalString s = constant.IsString( IsChild(node, "source-actor") ) )
{
Actor actor = root.FindChildByName(*s);
if(actor)
}
}
- if( OptionalString s = IsString( IsChild(node, "camera-actor") ) )
+ if( OptionalString s = constant.IsString( IsChild(node, "camera-actor") ) )
{
CameraActor actor = CameraActor::DownCast( root.FindChildByName(*s) );
if(actor)
}
}
- if( OptionalString s = IsString( IsChild(node, "target-frame-buffer") ) )
+ if( OptionalString s = constant.IsString( IsChild(node, "target-frame-buffer") ) )
{
- FrameBufferImage fb = GetFrameBufferImage( *s );
+ FrameBufferImage fb = GetFrameBufferImage( *s, constant );
if(fb)
{
task.SetTargetFrameBuffer( fb );
}
}
- if( OptionalString s = IsString( IsChild(node, "screen-to-frame-buffer-function") ) )
+ if( OptionalString s = constant.IsString( IsChild(node, "screen-to-frame-buffer-function") ) )
{
if("DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION" == *s)
{
}
// other setup is via the property system
- SetProperties( node, task, *this ); // @ todo, remove 'source-actor', 'camera-actor'?
+ SetProperties( node, task, *this, constant ); // @ todo, remove 'source-actor', 'camera-actor'?
}
void Builder::CreateRenderTask( const std::string &name )
{
+ Replacement constant(mReplacementMap);
+
const Stage& stage = Stage::GetCurrent();
OptionalChild tasks = IsChild(*mParser.GetRoot(), "render-tasks");
TreeNode::ConstIterator iter = (*renderTask).CBegin();
task = list.GetTask( start - 1 );
- SetupTask( task, (*iter).second );
+ SetupTask( task, (*iter).second, constant );
++iter;
for(; iter != (*renderTask).CEnd(); ++iter )
{
task = list.CreateTask();
- SetupTask( task, (*iter).second );
+ SetupTask( task, (*iter).second, constant );
}
}
}
}
-ShaderEffect Builder::GetShaderEffect( const std::string &name )
+ShaderEffect Builder::GetShaderEffect( const std::string &name)
+{
+ Replacement constant;
+ return GetShaderEffect( name, constant );
+}
+
+ShaderEffect Builder::GetShaderEffect( const std::string &name, const Replacement& constant )
{
ShaderEffect ret;
if( OptionalChild effect = IsChild( *effects, name ) )
{
Dali::Property::Value propertyMap(Property::MAP);
- if( SetPropertyFromNode( *effect, Property::MAP, propertyMap ) )
+ if( SetPropertyFromNode( *effect, Property::MAP, propertyMap, constant ) )
{
ret = Dali::Scripting::NewShaderEffect( propertyMap );
mShaderEffectLut[ name ] = ret;
FrameBufferImage Builder::GetFrameBufferImage( const std::string &name )
{
+ Replacement constant;
+ return GetFrameBufferImage(name, constant);
+}
+
+FrameBufferImage Builder::GetFrameBufferImage( const std::string &name, const Replacement& constant )
+{
FrameBufferImage ret;
ImageLut::const_iterator iter( mFrameBufferImageLut.find( name ) );
if( OptionalChild image = IsChild( *images, name ) )
{
Dali::Property::Value propertyMap(Property::MAP);
- if( SetPropertyFromNode( *image, Property::MAP, propertyMap ) )
+ if( SetPropertyFromNode( *image, Property::MAP, propertyMap, constant ) )
{
propertyMap.SetValue("type", Property::Value(std::string("FrameBufferImage")));
ret = Dali::Scripting::NewImage( propertyMap );
void Builder::AddActors( const std::string §ionName, Actor toActor )
{
+ PropertyValueMap overrideMap;
+ Replacement replacements(overrideMap, mReplacementMap);
+
OptionalChild addToStage = IsChild(*mParser.GetRoot(), sectionName);
if( addToStage )
for( TreeNode::ConstIterator iter = (*addToStage).CBegin(); iter != (*addToStage).CEnd(); ++iter )
{
// empty actor adds directly to the stage
- BaseHandle baseHandle = Create( mSlotDelegate.GetConnectionTracker(), styles, (*iter).second, *mParser.GetRoot(), Actor(), *this);
+ BaseHandle baseHandle = Create( styles, (*iter).second, *mParser.GetRoot(), Actor(), replacements );
Actor actor = Actor::DownCast(baseHandle);
if(actor)
{
}
}
}
-
}
}
-Animation Builder::CreateAnimation( const std::string& animationName )
+Animation Builder::CreateAnimation( const std::string& animationName, const Replacement& replacement, Dali::Actor searchRoot )
{
Animation anim;
{
if( OptionalChild animation = IsChild(*animations, animationName) )
{
- anim = Dali::Toolkit::Internal::CreateAnimation( *animation );
+ anim = Dali::Toolkit::Internal::CreateAnimation( *animation, replacement, Stage::GetCurrent().GetRootLayer() );
+ }
+ else
+ {
+ DALI_SCRIPT_WARNING( "Request for Animation called '%s' failed\n", animationName.c_str() );
}
}
else
{
- DALI_SCRIPT_WARNING( "Request for Animation called '%s' failed\n", animationName.c_str() );
+ DALI_SCRIPT_WARNING( "Request for Animation called '%s' failed (no animation section)\n", animationName.c_str() );
}
return anim;
}
+Animation Builder::CreateAnimation( const std::string& animationName, const PropertyValueMap& map, Dali::Actor searchRoot )
+{
+ Replacement replacement(map, mReplacementMap);
+ return CreateAnimation( animationName, replacement, searchRoot);
+}
+
+Animation Builder::CreateAnimation( const std::string& animationName, const PropertyValueMap& map )
+{
+ Replacement replacement(map, mReplacementMap);
+ return CreateAnimation( animationName, replacement, Stage::GetCurrent().GetRootLayer() );
+}
+
+Animation Builder::CreateAnimation( const std::string& animationName, Dali::Actor searchRoot )
+{
+ Replacement replacement( mReplacementMap );
+
+ return CreateAnimation( animationName, replacement, searchRoot );
+}
+
+Animation Builder::CreateAnimation( const std::string& animationName )
+{
+ Replacement replacement( mReplacementMap );
+ return CreateAnimation( animationName, replacement, Dali::Stage::GetCurrent().GetRootLayer() );
+}
+
void Builder::LoadFromString( std::string const& data, Dali::Toolkit::Builder::UIFormat format )
{
DALI_ASSERT_ALWAYS( format == Dali::Toolkit::Builder::JSON && "Currently only JSON is supported" );
DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Cannot parse JSON");
+ // load constant map (allows the user to override the constants in the json after loading)
+ LoadConstants();
+
+}
+
+void Builder::AddConstants( const PropertyValueMap& map )
+{
+ for(PropertyValueMap::const_iterator iter = map.begin(); iter != map.end(); ++iter)
+ {
+ mReplacementMap[ (*iter).first ] = (*iter).second;
+ }
+}
+
+void Builder::LoadConstants()
+{
+ Replacement replacer(mReplacementMap);
+
+ if( OptionalChild constants = IsChild(*mParser.GetRoot(), "constants") )
+ {
+ for(TreeNode::ConstIterator iter = (*constants).CBegin();
+ iter != (*constants).CEnd(); ++iter)
+ {
+ Dali::Property::Value property;
+ if( (*iter).second.GetName() )
+ {
+#if defined(DEBUG_ENABLED)
+ DALI_SCRIPT_VERBOSE("Constant set from json '%s'\n", (*iter).second.GetName());
+#endif
+ if( SetPropertyFromNode( (*iter).second, property, replacer ) )
+ {
+ mReplacementMap[ (*iter).second.GetName() ] = property;
+ }
+ else
+ {
+ DALI_SCRIPT_WARNING("Cannot convert property for constant %s\n",
+ (*iter).second.GetName() == NULL ? "no name?" : (*iter).second.GetName());
+ }
+ }
+ }
+ }
+
+#if defined(DEBUG_ENABLED)
+ PropertyValueMap::const_iterator iter = mReplacementMap.find( "CONFIG_SCRIPT_LOG_LEVEL" );
+ if( iter != mReplacementMap.end() && (*iter).second.GetType() == Property::STRING )
+ {
+ std::string logLevel( (*iter).second.Get< std::string >() );
+ if( logLevel == "NoLogging" )
+ {
+ gFilterScript->SetLogLevel( Integration::Log::NoLogging );
+ }
+ else if( logLevel == "Concise" )
+ {
+ gFilterScript->SetLogLevel( Integration::Log::Concise );
+ }
+ else if( logLevel == "General" )
+ {
+ gFilterScript->SetLogLevel( Integration::Log::General );
+ }
+ else if( logLevel == "Verbose" )
+ {
+ gFilterScript->SetLogLevel( Integration::Log::Verbose );
+ }
+ }
+#endif
+
}
void Builder::ApplyStyle( const std::string& styleName, Handle& handle )
{
+ Replacement replacer;
+ ApplyStyle( styleName, handle, replacer );
+}
+
+void Builder::ApplyStyle( const std::string& styleName, Handle& handle, const Replacement& replacement )
+{
OptionalChild styles = IsChild(*mParser.GetRoot(), "styles");
if( styles )
for(TreeNodeList::reverse_iterator iter = allStyles.rbegin(); iter != allStyles.rend(); ++iter)
{
- SetProperties( *style, handle, *this );
+ if( (*iter)->GetType() == TreeNode::ARRAY )
+ {
+ // if its an array then its a list of styles to set to objects already in the hiearchy by name
+ if( Dali::Actor actor = Dali::Actor::DownCast( handle ) )
+ {
+ const TreeNode& styleList = *(*iter);
+ for( TreeNode::ConstIterator iterSubStyle = styleList.CBegin(); iterSubStyle != styleList.CEnd(); ++iterSubStyle )
+ {
+ const TreeNode* nameNode = (*iterSubStyle).second.Find("name");
+ if( nameNode && nameNode->GetType() == TreeNode::STRING )
+ {
+ Dali::Actor found = actor.FindChildByName( nameNode->GetString() );
+ if( found )
+ {
+ SetProperties( (*iterSubStyle).second, found, *this, replacement );
+ }
+ else
+ {
+ DALI_SCRIPT_VERBOSE("Cannot find object '%s' in tree to style\n", nameNode->GetString());
+ }
+ }
+ else
+ {
+ DALI_SCRIPT_VERBOSE("Style name is not a string '%s' '%d'\n",
+ nameNode->GetString(), (*iterSubStyle).second.GetType());
+ }
+ }
+ }
+ else
+ {
+ DALI_SCRIPT_VERBOSE("Cannot apply style list to non actor\n");
+ }
+ }
+ else
+ {
+ DALI_ASSERT_DEBUG( (*iter)->GetType() == TreeNode::OBJECT );
+ SetProperties( *style, handle, *this, replacement );
+ }
}
}
else
}
}
-BaseHandle Builder::CreateFromStyle( const std::string& styleName )
+BaseHandle Builder::CreateFromStyle( const std::string& styleName, const PropertyValueMap& map )
+{
+ Replacement replacement( map, mReplacementMap );
+ return CreateFromStyle( styleName, replacement );
+}
+
+BaseHandle Builder::CreateFromStyle( const std::string& styleName, const Replacement& constant )
{
BaseHandle baseHandle;
}
else
{
- OptionalString type = IsString( IsChild(*style, "type") );
+ OptionalString type = constant.IsString( IsChild(*style, "type") );
if(!type)
{
}
else
{
- baseHandle = Create( mSlotDelegate.GetConnectionTracker(), styles, *style, *mParser.GetRoot(), Actor(), *this );
+ baseHandle = Create( styles, *style, *mParser.GetRoot(), Actor(), constant );
}
}
}
return baseHandle;
}
+
+BaseHandle Builder::CreateFromStyle( const std::string& styleName )
+{
+ PropertyValueMap overrideMap;
+ Replacement replacement( overrideMap, mReplacementMap );
+ return CreateFromStyle( styleName, replacement );
+}
+
Builder::Builder()
: mSlotDelegate( this )
{
// INTERNAL INCLUDES
#include <dali-toolkit/public-api/builder/json-parser.h>
#include <dali-toolkit/public-api/builder/builder.h>
+#include <dali-toolkit/internal/builder/builder-declarations.h>
// Warning messages usually displayed
#define DALI_SCRIPT_WARNING(format, args...) \
#endif
class Builder;
+class Replacement;
/**
* @copydoc Toolkit::Builder
Dali::Toolkit::Builder::UIFormat rep = Dali::Toolkit::Builder::JSON );
/**
- * @copydoc Toolkit::Builder::CreateAnimation
+ * @copydoc Toolkit::Builder::AddConstants
+ */
+ void AddConstants( const PropertyValueMap& map );
+
+ /**
+ * @copydoc Toolkit::Builder::CreateAnimation( const std::string& animationName );
*/
Animation CreateAnimation( const std::string& animationName );
/**
- * @copydoc Toolkit::Builder::CreateFromStyle
+ * @copydoc Toolkit::Builder::CreateAnimation( const std::string& animationName, const PropertyValueMap& map );
+ */
+ Animation CreateAnimation( const std::string& animationName, const PropertyValueMap& map );
+
+ /**
+ * @copydoc Toolkit::Builder::CreateAnimation( const std::string& animationName, Dali::Actor searchRoot );
+ */
+ Animation CreateAnimation( const std::string& animationName, Dali::Actor searchRoot );
+
+ /**
+ * @copydoc Toolkit::Builder::CreateAnimation( const std::string& animationName, const PropertyValueMap& map, Dali::Actor searchRoot );
+ */
+ Animation CreateAnimation( const std::string& animationName, const PropertyValueMap& map, Dali::Actor searchRoot );
+
+ /**
+ * @copydoc Toolkit::Builder::CreateFromStyle( const std::string& styleName );
*/
BaseHandle CreateFromStyle( const std::string& styleName );
/**
+ * @copydoc Toolkit::Builder::CreateFromStyle( const std::string& styleName, const PropertyValueMap& map );
+ */
+ BaseHandle CreateFromStyle( const std::string& styleName, const PropertyValueMap& map );
+
+ /**
* @copydoc Toolkit::Builder::GetFont
*/
Font GetFont(const std::string &name) const;
ShaderEffect GetShaderEffect( const std::string &name );
/**
+ * @copydoc Toolkit::Builder::GetShaderEffect
+ */
+ ShaderEffect GetShaderEffect( const std::string &name, const Replacement& constant );
+
+ /**
* @copydoc Toolkit::Builder::GetFrameBufferImage
*/
FrameBufferImage GetFrameBufferImage( const std::string &name );
/**
+ * @copydoc Toolkit::Builder::GetFrameBufferImage
+ */
+ FrameBufferImage GetFrameBufferImage( const std::string &name, const Replacement& constant );
+
+ /**
* @copydoc Toolkit::Builder::GetTopLevelActors
*/
ActorContainer GetTopLevelActors( void ) const;
Builder(const Builder&);
Builder& operator=(const Builder& rhs);
- void SetupTask( RenderTask& task, const Toolkit::TreeNode& node );
+ void SetupTask( RenderTask& task, const Toolkit::TreeNode& node, const Replacement& replacement );
private:
Toolkit::JsonParser mParser;
ShaderEffectLut mShaderEffectLut;
SlotDelegate<Builder> mSlotDelegate;
+
+ PropertyValueMap mReplacementMap;
+
+ BaseHandle Create( const OptionalChild& optionalStyles, const TreeNode& node, const TreeNode& root, Actor parent,
+ const Replacement& replacement );
+
+ void LoadConstants();
+
+ void ApplyStyle( const std::string& styleName, Handle& handle, const Replacement& replacement);
+
+ Animation CreateAnimation( const std::string& animationName, const Replacement& replacement, Dali::Actor searchRoot );
+
+ BaseHandle CreateFromStyle( const std::string& styleName, const Replacement& replacement );
};
} // namespace Internal
// INTERNAL INCLUDES
#include <dali-toolkit/internal/builder/builder-impl.h>
#include <dali-toolkit/internal/builder/builder-get-is.inl.h>
+#include <dali-toolkit/internal/builder/replacement.h>
namespace Dali
{
bool SetPropertyFromNode( const TreeNode& node, Property::Value& value );
/*
+ * Set a property value from a tree node as SetPropertyFromNode() above
+ * @param node The node string to convert from
+ * @param value The property value to set
+ * @param replacement The overriding replacement map (if any)
+ * @return true if the string could be converted.
+ */
+bool SetPropertyFromNode( const TreeNode& node, Property::Value& value,
+ const Replacement& replacement );
+
+/*
* Set a property value as the given type from a tree node.
* @param node The node string to convert from
* @param type The property type to convert to.
*/
bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value );
+/*
+ * Set a property value as the given type from a tree node as SetPropertyFromNode() above
+ * @param node The node string to convert from
+ * @param type The property type to convert to.
+ * @param value The property value to set
+ * @param replacement The overriding replacement map (if any)
+ * @return true if the string could be converted to the correct type.
+ */
+bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value,
+ const Replacement& replacement );
+
+
+namespace
+{
+
+
+
+} // anon namespace
+
+
/**
* A property value type can be forced when its unknown by a disambiguation convention in the json
* ie "myarray": [1,2,3,4] ; would be a vector but
* "myarray": {'type-cast':'array', 'value':[1,2,3,4]} would be an array
* @param child The node whos string to search for a disambiguated type
* @param value The value to set
+ * @param overrideMap The user overriding constant map
+ * @param defaultMap The default map.
* @return True if child contained a disambiguated string that could be converted.
*/
bool Disambiguated(const TreeNode& child, // ConstantLut& constantLut,
- Dali::Property::Value& value)
+ Dali::Property::Value& value,
+ const Replacement& replacement )
{
OptionalString childType = IsString( IsChild(child, "type-cast") );
OptionalChild childValue = IsChild(child, "value");
// type-cast and value keys. If they do then a work around is to add a bogus key to not run this case.
if(*childType == "boolean")
{
- return SetPropertyFromNode( *childValue, Dali::Property::BOOLEAN, value);
+ return SetPropertyFromNode( *childValue, Dali::Property::BOOLEAN, value, replacement);
}
else if(*childType == "float")
{
- return SetPropertyFromNode( *childValue, Dali::Property::FLOAT, value);
+ return SetPropertyFromNode( *childValue, Dali::Property::FLOAT, value, replacement);
}
else if(*childType == "vector2")
{
- return SetPropertyFromNode( *childValue, Dali::Property::VECTOR2, value);
+ return SetPropertyFromNode( *childValue, Dali::Property::VECTOR2, value, replacement);
}
else if(*childType == "vector3")
{
- return SetPropertyFromNode( *childValue, Dali::Property::VECTOR3, value);
+ return SetPropertyFromNode( *childValue, Dali::Property::VECTOR3, value, replacement);
}
else if(*childType == "vector4")
{
- return SetPropertyFromNode( *childValue, Dali::Property::VECTOR4, value);
+ return SetPropertyFromNode( *childValue, Dali::Property::VECTOR4, value, replacement);
}
else if(*childType == "rotation")
{
- return SetPropertyFromNode( *childValue, Dali::Property::ROTATION, value);
+ return SetPropertyFromNode( *childValue, Dali::Property::ROTATION, value, replacement);
}
else if(*childType == "rect")
{
- return SetPropertyFromNode( *childValue, Dali::Property::RECTANGLE, value);
+ return SetPropertyFromNode( *childValue, Dali::Property::RECTANGLE, value, replacement);
}
else if(*childType == "string")
{
- return SetPropertyFromNode( *childValue, Dali::Property::STRING, value);
+ return SetPropertyFromNode( *childValue, Dali::Property::STRING, value, replacement);
}
else if(*childType == "map")
{
- return SetPropertyFromNode( *childValue, Dali::Property::MAP, value);
+ return SetPropertyFromNode( *childValue, Dali::Property::MAP, value, replacement);
}
else if(*childType == "array")
{
- return SetPropertyFromNode( *childValue, Dali::Property::ARRAY, value);
+ return SetPropertyFromNode( *childValue, Dali::Property::ARRAY, value, replacement);
}
}
return false;
}
-bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value )
+
+bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value)
+{
+ Replacement noReplacement;
+ return SetPropertyFromNode( node, type, value, noReplacement );
+}
+
+bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value,
+ const Replacement& replacer )
{
bool done = false;
{
case Property::BOOLEAN:
{
- if( OptionalBoolean v = IsBoolean(node) )
+ if( OptionalBoolean v = replacer.IsBoolean(node) )
{
value = *v;
done = true;
}
case Property::FLOAT:
{
- if( OptionalFloat v = IsFloat(node) )
+ if( OptionalFloat v = replacer.IsFloat(node) )
{
value = *v;
done = true;
}
case Property::INTEGER:
{
- if( OptionalInteger v = IsInteger(node) )
+ if( OptionalInteger v = replacer.IsInteger(node) )
{
value = *v;
done = true;
}
case Property::UNSIGNED_INTEGER:
{
- if( OptionalInteger v = IsInteger(node) )
+ if( OptionalInteger v = replacer.IsInteger(node) )
{
if( *v >= 0 ) // with a loss of resolution....
{
}
case Property::VECTOR2:
{
- if( OptionalVector2 v = IsVector2(node) )
+ if( OptionalVector2 v = replacer.IsVector2(node) )
{
value = *v;
done = true;
}
case Property::VECTOR3:
{
- if( OptionalVector3 v = IsVector3(node) )
+ if( OptionalVector3 v = replacer.IsVector3(node) )
{
value = *v;
done = true;
}
case Property::VECTOR4:
{
- if( OptionalVector4 v = IsVector4(node) )
+ if( OptionalVector4 v = replacer.IsVector4(node) )
{
value = *v;
done = true;
- }
+ }
break;
}
case Property::MATRIX3:
{
- if( OptionalMatrix3 v = IsMatrix3(node) )
+ if( OptionalMatrix3 v = replacer.IsMatrix3(node) )
{
value = *v;
done = true;
}
case Property::MATRIX:
{
- if( OptionalMatrix v = IsMatrix(node) )
+ if( OptionalMatrix v = replacer.IsMatrix(node) )
{
value = *v;
done = true;
}
case Property::RECTANGLE:
{
- if( OptionalRect v = IsRect(node) )
+ if( OptionalRect v = replacer.IsRect(node) )
{
value = *v;
done = true;
{
if(4 == node.Size())
{
- if( OptionalVector4 ov = IsVector4(node) )
+ if( OptionalVector4 ov = replacer.IsVector4(node) )
{
const Vector4& v = *ov;
// angle, axis as per spec
else
{
// degrees Euler as per spec
- if( OptionalVector3 v = IsVector3(node) )
+ if( OptionalVector3 v = replacer.IsVector3(node) )
{
value = Quaternion(Radian(Degree((*v).x)),
Radian(Degree((*v).y)),
}
case Property::STRING:
{
- if( OptionalString v = IsString(node) )
+ if( OptionalString v = replacer.IsString(node) )
{
value = *v;
done = true;
}
case Property::ARRAY:
{
- if(node.Size())
+ if( replacer.IsArray( node, value ) )
+ {
+ done = true;
+ }
+ else if(node.Size())
{
value = Property::Value(Property::ARRAY);
unsigned int i = 0;
for( ; i < node.Size(); ++i, ++iter)
{
Property::Value v;
- if( SetPropertyFromNode( (*iter).second, v) )
+ if( SetPropertyFromNode( (*iter).second, v, replacer ) )
{
value.AppendItem(v);
}
}
case Property::MAP:
{
- if(node.Size())
+ if( replacer.IsMap( node, value ) )
+ {
+ done = true;
+ }
+ else if(node.Size())
{
value = Property::Value(Property::MAP);
unsigned int i = 0;
for( ; i < node.Size(); ++i, ++iter)
{
Property::Value v;
- if( SetPropertyFromNode( (*iter).second, v) )
+ if( SetPropertyFromNode( (*iter).second, v, replacer ) )
{
value.SetValue( (*iter).first, v );
}
{
break;
}
- }
+ } // switch type
return done;
}
-
bool SetPropertyFromNode( const TreeNode& node, Property::Value& value )
+
+{
+ Replacement replacer;
+ return SetPropertyFromNode( node, value, replacer );
+}
+
+bool SetPropertyFromNode( const TreeNode& node, Property::Value& value,
+ const Replacement& replacer )
{
bool done = false;
// some values are ambiguous as we have no Property::Type but can be disambiguated in the json
// Currently Rotations and Rectangle must always be disambiguated when a type isnt available
- if( Disambiguated( node, value ) )
+ if( Disambiguated( node, value, replacer ) )
{
done = true;
}
value = *v;
done = true;
}
- if( OptionalVector4 v = IsVector4(node) )
+ else if( OptionalVector4 v = IsVector4(node) )
{
value = *v;
done = true;
for(TreeConstIter iter = node.CBegin(); iter != node.CEnd(); ++iter)
{
- if( SetPropertyFromNode( (*iter).second, v) )
+ if( SetPropertyFromNode( (*iter).second, v, replacer ) )
{
value.AppendItem(v);
done = true;
Property::Value v;
for(unsigned int i = 0; i < node.Size(); ++i, ++iter)
{
- if( SetPropertyFromNode( (*iter).second, v) )
+ if( SetPropertyFromNode( (*iter).second, v, replacer ) )
{
value.AppendItem(v);
done = true;
Property::Value v;
for(unsigned int i = 0; i < node.Size(); ++i, ++iter)
{
- if( SetPropertyFromNode( (*iter).second, v) )
+ if( SetPropertyFromNode( (*iter).second, v, replacer ) )
{
value.SetValue((*iter).first, v);
done = true;
else // if( 0 == node.size() )
{
// no children so either one of bool, float, integer, string
- OptionalBoolean aBool = IsBoolean(node);
- OptionalInteger anInt = IsInteger(node);
- OptionalFloat aFloat = IsFloat(node);
- OptionalString aString = IsString(node);
+ OptionalBoolean aBool = replacer.IsBoolean(node);
+ OptionalInteger anInt = replacer.IsInteger(node);
+ OptionalFloat aFloat = replacer.IsFloat(node);
+ OptionalString aString = replacer.IsString(node);
if(aBool)
{
{
DelayedAnimationPlay action;
action.memento = Toolkit::JsonParser::New(*animNode);
+ // @todo; put constants into the map
callback = action;
}
else
mNumberOfParsedChars += last - first;
mNumberOfParsedChars += 1 ; // null terminator
+ mCurrent.SetSubstitution( substitution > 1 );
+
// return true;
return &(*first);
--- /dev/null
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://floralicense.org/license/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/builder/replacement.h>
+#include <dali-toolkit/internal/builder/builder-impl.h>
+#include <dali-toolkit/internal/builder/builder-get-is.inl.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+namespace // anon
+{
+
+PropertyValueMap::const_iterator FindReplacement( const std::string &str,
+ const PropertyValueMap& overrideMap, const PropertyValueMap& defaultMap )
+{
+ PropertyValueMap::const_iterator ret = defaultMap.end();
+
+ PropertyValueMap::const_iterator iter = overrideMap.find( str );
+
+ if( iter != overrideMap.end() )
+ {
+ ret = iter;
+ }
+ else
+ {
+ PropertyValueMap::const_iterator iter = defaultMap.find( str );
+
+ if( iter != defaultMap.end() )
+ {
+ ret = iter;
+ }
+ else
+ {
+ // @ todo
+ // try localized text ie dgettext. Look for colon {DOMAIN:TEXT} {LC_MESSAGE:ID_XXXX}
+
+ }
+ }
+
+ return ret;
+}
+
+std::size_t FirstUnescapedChar(const std::string &initialValue, const std::size_t& startPos, const char c)
+{
+ std::size_t pos = initialValue.find( c, startPos );
+
+ if(pos > 0)
+ {
+ while( pos != std::string::npos )
+ {
+ if( '\\' == initialValue.at( pos-1 ) )
+ {
+ pos = initialValue.find( c, pos );
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ return pos;
+}
+
+bool GetSubstitutionPosition( const std::string &initialValue, std::size_t &startPos, std::size_t &size )
+{
+ std::size_t pos = FirstUnescapedChar(initialValue, 0, '{');
+
+ if( std::string::npos == pos )
+ {
+ startPos = std::string::npos;
+ return false;
+ }
+ else
+ {
+ startPos = pos + 1;
+ }
+
+ pos = FirstUnescapedChar(initialValue, startPos, '}');
+
+ if( std::string::npos == pos )
+ {
+ size = std::string::npos;
+ return false;
+ }
+ else
+ {
+ size = pos - startPos;
+ }
+
+ return true;
+}
+
+bool ResolvePartialReplacement( const std::string &initialValue, Property::Value &out,
+ const PropertyValueMap& overrideMap, const PropertyValueMap& defaultMap )
+{
+
+ if( initialValue.size() >= 2 )
+ {
+ // eg '{"constants": { "IMAGE_DIR": "/share/images" },
+ // ...
+ // "filename":"{IMAGE_DIR}/theme/header.png",
+ //
+ std::size_t startPos = 0;
+ std::size_t size = std::string::npos;
+
+ if( !GetSubstitutionPosition( initialValue, startPos, size ) )
+ {
+ out = initialValue;
+ return true;
+ }
+ else
+ {
+ const std::string str( initialValue.substr( startPos, size ) );
+
+ PropertyValueMap::const_iterator iter = FindReplacement( str, overrideMap, defaultMap );
+
+ if( iter == defaultMap.end() )
+ {
+ DALI_SCRIPT_WARNING( "Cannot find replacement for '%s'\n", str.c_str() );
+ }
+ else
+ {
+ if( Property::STRING != (*iter).second.GetType() )
+ {
+ DALI_SCRIPT_WARNING( "Cannot replace substring in non string property type='%s'. Initial value '%s'\n",
+ PropertyTypes::GetName( out.GetType() ), initialValue.c_str() );
+ }
+ else
+ {
+ std::string newString = \
+ initialValue.substr(0, startPos - 1) +
+ (*iter).second.Get<std::string>() +
+ initialValue.substr( startPos + size + 1 );
+
+ return ResolvePartialReplacement( newString, out, overrideMap, defaultMap );
+ }
+ }
+ }
+ }
+
+ // if we get here we failed
+ return false;
+}
+
+} // namespace anon
+
+
+Replacement::Replacement( const PropertyValueMap& overrideMap, const PropertyValueMap& defaultMap )
+ : mOverrideMap( &overrideMap ), mDefaultMap( &defaultMap )
+{
+
+}
+
+namespace
+{
+PropertyValueMap noMap;
+}
+
+Replacement::Replacement( const PropertyValueMap& defaultMap )
+ : mOverrideMap( &noMap ), mDefaultMap( &defaultMap )
+{
+
+}
+
+Replacement::Replacement( )
+ : mOverrideMap( &noMap ), mDefaultMap( &noMap )
+{
+
+}
+
+OptionalString Replacement::HasFullReplacement( const TreeNode & node ) const
+{
+ OptionalString ret;
+
+ if( node.HasSubstitution() && ((*mOverrideMap).size() || (*mDefaultMap).size()) )
+ {
+ OptionalString v = ::IsString( node );
+ if( v )
+ {
+ const std::string& initialValue = *v;
+ if( (initialValue[ 0 ] == '{') && (initialValue[ initialValue.size() -1 ] == '}') )
+ {
+ ret = initialValue.substr( 1, initialValue.size() - 2 );
+ }
+ }
+ }
+ return ret;
+}
+
+Property::Value Replacement::GetFullReplacement( const std::string& replacementString ) const
+{
+ Property::Value out;
+ DALI_ASSERT_DEBUG( mOverrideMap && "missing map");
+ DALI_ASSERT_DEBUG( mDefaultMap && "missing map");
+
+ PropertyValueMap::const_iterator iter = FindReplacement( replacementString, *mOverrideMap, *mDefaultMap );
+
+ if( iter == (*mDefaultMap).end() )
+ {
+ DALI_SCRIPT_WARNING("Cannot find replacement for '%s'\n", replacementString.c_str());
+ }
+ else
+ {
+ out = (*iter).second;
+#if defined(DEBUG_ENABLED)
+ DALI_SCRIPT_VERBOSE(" Full replacement for '%s' => to Type '%s'\n",
+ replacementString.c_str(),
+ PropertyTypes::GetName( out.GetType()) );
+#endif
+ }
+
+ return out;
+}
+
+OptionalBoolean Replacement::IsBoolean( const TreeNode & node ) const
+{
+ OptionalBoolean ret;
+ if( OptionalString replace = HasFullReplacement( node ) )
+ {
+ Property::Value value = GetFullReplacement( *replace );
+ if( Property::BOOLEAN == value.GetType() )
+ {
+ ret = value.Get<bool>();
+ }
+ }
+ else
+ {
+ ret = ::IsBoolean( node );
+ }
+ return ret;
+}
+
+OptionalBoolean Replacement::IsBoolean( OptionalChild child ) const
+{
+ if( child )
+ {
+ return IsBoolean( *child );
+ }
+ else
+ {
+ return OptionalBoolean();
+ }
+}
+
+// template <typename T, OptionalValue<T> (*ISTYPE)( const TreeNode& node ), Property::Type TYPE>
+// OptionalValue<T> IsOfType( const TreeNode& node, const PropertyValueMap& overrideMap, const PropertyValueMap& defaultMap )
+// {
+// OptionalValue<T> ret;
+// if( OptionalString replace = HasFullReplacement( node, overrideMap, defaultMap ) )
+// {
+// Property::Value value = GetFullReplacement( *replace, overrideMap, defaultMap );
+// if( TYPE == value.GetType() )
+// {
+// ret = value.Get<T>();
+// }
+// }
+// else
+// {
+// ret = ISTYPE( node );
+// }
+// return ret;
+
+// }
+
+// OptionalFloat Replacement::IsFloat( const TreeNode & node ) const
+// {
+// return IsOfType<float, ::IsFloat, Property::FLOAT>( node, *mOverrideMap, *mDefaultMap );
+// /* OptionalFloat ret; */
+// /* if( OptionalString replace = HasFullReplacement( node ) ) */
+// /* { */
+// /* Property::Value value = GetFullReplacement( replace ); */
+// /* if( Property::FLOAT == value.GetType() ) */
+// /* { */
+// /* ret = value.Get<float>(); */
+// /* } */
+// /* } */
+// /* else */
+// /* { */
+// /* ret = IsFloat( node ); */
+// /* } */
+// /* return ret; */
+// }
+
+OptionalFloat Replacement::IsFloat( const TreeNode & node ) const
+{
+ OptionalFloat ret;
+ if( OptionalString replace = HasFullReplacement( node ) )
+ {
+ Property::Value value = GetFullReplacement( *replace );
+ if( Property::FLOAT == value.GetType() )
+ {
+ ret = value.Get<float>();
+ }
+ }
+ else
+ {
+ ret = ::IsFloat( node );
+ }
+ return ret;
+}
+
+OptionalString Replacement::IsString( const TreeNode& node ) const
+{
+ OptionalString ret;
+
+ DALI_ASSERT_DEBUG( mOverrideMap && "missing map");
+ DALI_ASSERT_DEBUG( mDefaultMap && "missing map");
+
+ if( node.HasSubstitution() && ((*mOverrideMap).size() || (*mDefaultMap).size()) )
+ {
+ if( OptionalString v = ::IsString( node ) )
+ {
+ Property::Value value;
+ if( ResolvePartialReplacement( *v, value, *mOverrideMap, *mDefaultMap ) )
+ {
+ if( Property::STRING == value.GetType() )
+ {
+ ret = value.Get<std::string>();
+#if defined(DEBUG_ENABLED)
+ DALI_SCRIPT_VERBOSE(" Resolved substring replacement for '%s' => '%s'\n", (*v).c_str(), (*ret).c_str());
+#endif
+ }
+ }
+ }
+ }
+ else
+ {
+ ret = ::IsString( node );
+ }
+ return ret;
+}
+
+OptionalInteger Replacement::IsInteger( const TreeNode & node ) const
+{
+ OptionalInteger ret;
+ if( OptionalString replace = HasFullReplacement( node ) )
+ {
+ Property::Value value = GetFullReplacement( *replace );
+ if( Property::INTEGER == value.GetType() )
+ {
+ ret = value.Get<int>();
+ }
+ }
+ else
+ {
+ ret = ::IsInteger( node );
+ }
+ return ret;
+}
+
+OptionalVector2 Replacement::IsVector2( const TreeNode & node ) const
+{
+ OptionalVector2 ret;
+ if( OptionalString replace = HasFullReplacement( node ) )
+ {
+ Property::Value value = GetFullReplacement( *replace );
+ if( Property::VECTOR2 == value.GetType() )
+ {
+ ret = value.Get<Vector2>();
+ }
+ }
+ else
+ {
+ ret = ::IsVector2( node );
+ }
+ return ret;
+}
+
+OptionalVector3 Replacement::IsVector3( const TreeNode & node ) const
+{
+ OptionalVector3 ret;
+ if( OptionalString replace = HasFullReplacement( node ) )
+ {
+ Property::Value value = GetFullReplacement( *replace );
+ if( Property::VECTOR3 == value.GetType() )
+ {
+ ret = value.Get<Vector3>();
+ }
+ }
+ else
+ {
+ ret = ::IsVector3( node );
+ }
+ return ret;
+}
+
+OptionalVector4 Replacement::IsVector4( const TreeNode & node ) const
+{
+ OptionalVector4 ret;
+ if( OptionalString replace = HasFullReplacement( node ) )
+ {
+ Property::Value value = GetFullReplacement( *replace );
+ if( Property::VECTOR4 == value.GetType() )
+ {
+ ret = value.Get<Vector4>();
+ }
+ }
+ else
+ {
+ ret = ::IsVector4( node );
+ }
+ return ret;
+}
+
+OptionalMatrix Replacement::IsMatrix( const TreeNode & node ) const
+{
+ OptionalMatrix ret;
+ if( OptionalString replace = HasFullReplacement( node ) )
+ {
+ Property::Value value = GetFullReplacement( *replace );
+ if( Property::MATRIX == value.GetType() )
+ {
+ ret = value.Get<Matrix>();
+ }
+ }
+ else
+ {
+ ret = ::IsMatrix( node );
+ }
+ return ret;
+}
+
+OptionalMatrix3 Replacement::IsMatrix3( const TreeNode & node ) const
+{
+ OptionalMatrix3 ret;
+ if( OptionalString replace = HasFullReplacement( node ) )
+ {
+ Property::Value value = GetFullReplacement( *replace );
+ if( Property::MATRIX3 == value.GetType() )
+ {
+ ret = value.Get<Matrix3>();
+ }
+ }
+ else
+ {
+ ret = ::IsMatrix3( node );
+ }
+ return ret;
+}
+
+OptionalRect Replacement::IsRect( const TreeNode & node ) const
+{
+ OptionalRect ret;
+ if( OptionalString replace = HasFullReplacement( node ) )
+ {
+ Property::Value value = GetFullReplacement( *replace );
+ if( Property::RECTANGLE == value.GetType() )
+ {
+ ret = value.Get<Rect<int> >();
+ }
+ }
+ else
+ {
+ ret = ::IsRect( node );
+ }
+ return ret;
+}
+
+
+
+OptionalFloat Replacement::IsFloat( OptionalChild child ) const
+{
+ if( child )
+ {
+ return IsFloat( *child );
+ }
+ else
+ {
+ return OptionalFloat();
+ }
+}
+
+
+OptionalString Replacement::IsString( OptionalChild child ) const
+{
+ if( child )
+ {
+ return IsString( *child );
+ }
+ else
+ {
+ return OptionalString();
+ }
+}
+
+OptionalInteger Replacement::IsInteger( OptionalChild child ) const
+{
+ if( child )
+ {
+ return IsInteger( *child );
+ }
+ else
+ {
+ return OptionalInteger();
+ }
+}
+
+OptionalVector2 Replacement::IsVector2( OptionalChild child ) const
+{
+ if( child )
+ {
+ return IsVector2( *child );
+ }
+ else
+ {
+ return OptionalVector2();
+ }
+}
+
+OptionalVector3 Replacement::IsVector3( OptionalChild child ) const
+{
+ if( child )
+ {
+ return IsVector3( *child );
+ }
+ else
+ {
+ return OptionalVector3();
+ }
+}
+
+OptionalVector4 Replacement::IsVector4( OptionalChild child ) const
+{
+ if( child )
+ {
+ return IsVector4( *child );
+ }
+ else
+ {
+ return OptionalVector4();
+ }
+}
+
+OptionalMatrix Replacement::IsMatrix( OptionalChild child ) const
+{
+ if( child )
+ {
+ return IsMatrix( *child );
+ }
+ else
+ {
+ return OptionalMatrix();
+ }
+}
+
+OptionalMatrix3 Replacement::IsMatrix3( OptionalChild child ) const
+{
+ if( child )
+ {
+ return IsMatrix3( *child );
+ }
+ else
+ {
+ return OptionalMatrix3();
+ }
+}
+
+OptionalRect Replacement::IsRect( OptionalChild child ) const
+{
+ if( child )
+ {
+ return IsRect( *child );
+ }
+ else
+ {
+ return OptionalRect();
+ }
+}
+
+bool Replacement::IsMap( OptionalChild child, Property::Value& out ) const
+{
+ bool ret = false;
+
+ if( child )
+ {
+ if( OptionalString replace = HasFullReplacement( *child ) )
+ {
+ out = GetFullReplacement( *replace );
+ if( Property::MAP == out.GetType() )
+ {
+ ret = true;
+ }
+ }
+ }
+
+ return ret;
+}
+
+bool Replacement::IsArray( OptionalChild child, Property::Value& out ) const
+{
+ bool ret = false;
+
+ if( child )
+ {
+ if( OptionalString replace = HasFullReplacement( *child ) )
+ {
+ out = GetFullReplacement( *replace );
+ if( Property::ARRAY == out.GetType() )
+ {
+ ret = true;
+ }
+ }
+ }
+
+ return ret;
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
--- /dev/null
+#ifndef __DALI_TOOLKIT_INTERNAL_BUILDER_REPLACEMENT__
+#define __DALI_TOOLKIT_INTERNAL_BUILDER_REPLACEMENT__
+
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://floralicense.org/license/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <dali/public-api/object/property-value.h>
+#include <dali-toolkit/public-api/builder/builder.h>
+#include <dali-toolkit/internal/builder/builder-get-is.inl.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+ class TreeNode;
+}
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+/*
+ * Supports template replacement functionality
+ *
+ */
+class Replacement
+{
+public:
+
+ /*
+ * Constructor
+ */
+ Replacement();
+
+ /*
+ * Constructor with default and overriding map
+ *
+ * Make a deep copy of the tree.
+ * @param overrideMap The user overriding map
+ * @param defaultMap The default map to use
+ */
+ Replacement( const PropertyValueMap& overrideMap, const PropertyValueMap& defaultMap );
+
+ /*
+ * Constructor with default map
+ *
+ * Make a deep copy of the tree.
+ * @param overrideMap The user overriding map
+ */
+ Replacement( const PropertyValueMap& defaultMap );
+
+ /* @brief Check node for a type
+ *
+ * @param node The TreeNode to check
+ * @return Optional value
+ */
+ OptionalString IsString( const TreeNode& node ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param node The TreeNode to check
+ * @return Optional value
+ */
+ OptionalBoolean IsBoolean( const TreeNode & node ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param node The TreeNode to check
+ * @return Optional value
+ */
+ OptionalFloat IsFloat( const TreeNode & node ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param node The TreeNode to check
+ * @return Optional value
+ */
+ OptionalInteger IsInteger( const TreeNode & node ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param node The TreeNode to check
+ * @return Optional value
+ */
+ OptionalVector2 IsVector2( const TreeNode & node ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param node The TreeNode to check
+ * @return Optional value
+ */
+ OptionalVector3 IsVector3( const TreeNode & node ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param node The TreeNode to check
+ * @return Optional value
+ */
+ OptionalVector4 IsVector4( const TreeNode & node ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param node The TreeNode to check
+ * @return Optional value
+ */
+ OptionalMatrix IsMatrix( const TreeNode & node ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param node The TreeNode to check
+ * @return Optional value
+ */
+ OptionalMatrix3 IsMatrix3( const TreeNode & node ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param node The TreeNode to check
+ * @return Optional value
+ */
+ OptionalRect IsRect( const TreeNode & node ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param child The optional child TreeNode
+ * @return Optional value
+ */
+ OptionalString IsString( OptionalChild child ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param child The optional child TreeNode
+ * @return Optional value
+ */
+ OptionalFloat IsFloat( OptionalChild child ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param child The optional child TreeNode
+ * @return Optional value
+ */
+ OptionalBoolean IsBoolean( OptionalChild child ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param child The optional child TreeNode
+ * @return Optional value
+ */
+ OptionalInteger IsInteger( OptionalChild child ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param child The optional child TreeNode
+ * @return Optional value
+ */
+ OptionalVector2 IsVector2( OptionalChild child ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param child The optional child TreeNode
+ * @return Optional value
+ */
+ OptionalVector3 IsVector3( OptionalChild child ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param child The optional child TreeNode
+ * @return Optional value
+ */
+ OptionalVector4 IsVector4( OptionalChild child ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param child The optional child TreeNode
+ * @return Optional value
+ */
+ OptionalMatrix IsMatrix( OptionalChild child ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param child The optional child TreeNode
+ * @return Optional value
+ */
+ OptionalMatrix3 IsMatrix3( OptionalChild child ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param child The optional child TreeNode
+ * @return Optional value
+ */
+ OptionalRect IsRect( OptionalChild child ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param child The optional child TreeNode
+ * @return Optional value
+ */
+ bool IsMap( OptionalChild child, Property::Value& out ) const;
+
+ /* @brief Check node for a type
+ *
+ * @param child The optional child TreeNode
+ * @return Optional value
+ */
+ bool IsArray( OptionalChild child, Property::Value& out ) const;
+
+private:
+ // Overriding map (overrides the default map). The map is not owned.
+ const PropertyValueMap* const mOverrideMap;
+
+ // Defautl map. The map is not owned.
+ const PropertyValueMap* const mDefaultMap;
+
+ // compiler
+ // Replacement & operation=( Replacement& replacement );
+ // Replacement( const Replacement& copy );
+
+ // Returns the string if the node has a full replacement ie IMAGES if node is "{IMAGES}"
+ OptionalString HasFullReplacement( const TreeNode & node ) const;
+
+ // Returns the property value for a full replacement from the maps
+ Property::Value GetFullReplacement( const std::string& replacementString ) const;
+
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+
+#endif // header
$(toolkit_src_dir)/builder/json-parser-state.cpp \
$(toolkit_src_dir)/builder/json-parser-impl.cpp \
$(toolkit_src_dir)/builder/tree-node-manipulator.cpp \
+ $(toolkit_src_dir)/builder/replacement.cpp \
$(toolkit_src_dir)/controls/relayout-controller.cpp \
$(toolkit_src_dir)/controls/relayout-controller-impl.cpp \
$(toolkit_src_dir)/controls/relayout-helper.cpp \
GetImpl(*this).LoadFromString( data );
}
+void Builder::AddConstants( const PropertyValueMap& map )
+{
+ GetImpl(*this).AddConstants( map );
+}
+
Animation Builder::CreateAnimation( const std::string& animationName )
{
return GetImpl(*this).CreateAnimation( animationName );
}
+Animation Builder::CreateAnimation( const std::string& animationName, const PropertyValueMap& map )
+{
+ return GetImpl(*this).CreateAnimation( animationName, map );
+}
+
BaseHandle Builder::CreateFromStyle( const std::string& styleName )
{
return GetImpl(*this).CreateFromStyle( styleName );
}
+BaseHandle Builder::CreateFromStyle( const std::string& styleName, const PropertyValueMap& map )
+{
+ return GetImpl(*this).CreateFromStyle( styleName, map );
+}
+
void Builder::ApplyStyle( const std::string& styleName, Handle& handle )
{
GetImpl(*this).ApplyStyle( styleName, handle );
class Builder;
}
+typedef std::map<std::string, Property::Value> PropertyValueMap;
+
/**
* Builder
* This class provides the ability to load an actor tree from a string representation.
void LoadFromString( const std::string& data, UIFormat format = JSON );
/**
+ * @brief Adds user defined constants to all future style template or animation expansions
+ *
+ * e.g.
+ * PropertyValueMap map;
+ * map["IMAGE_DIRECTORY"] = "/usr/share/images";
+ * builder.AddConstants( map );
+ *
+ * @pre The Builder has been initialized.
+ * @param map The user defined constants used in template expansions.
+ */
+ void AddConstants( const PropertyValueMap& map );
+
+ /**
* Creates an animation from the set of known animations
* e.g.
* Animation a = builder.CreateAnimation( "wobble");
Animation CreateAnimation( const std::string& animationName );
/**
- * Creates an object (e.g. an actor) from the set of known styles
+ * @brief Creates an animation from the set of known animations with user defined constants
+ *
+ * e.g.
+ * PropertyValueMap map;
+ * map["ACTOR"] = actor.GetName(); // replaces '{ACTOR} in the template
+ * Animation a = builder.CreateAnimation( "wobble");
+ *
+ * @pre The Builder has been initialized.
+ * @pre Preconditions have been met for creating dali objects ie Images, Actors etc
+ * @pre The animationName exists in the animations section of the data representation
+ * @pre The map contains all the constant expansions in the style template
+ * @param animationName The animation name to create
+ * @param map The user defined constants used in style template expansion.
+ * @returns The base handle of the created object
+ */
+ Animation CreateAnimation( const std::string& animationName, const PropertyValueMap& map );
+
+ /**
+ * @brief Creates an object (e.g. an actor) from the set of known style templates
+ *
* e.g.
* mActor.Add( Actor::DownCast(builder.CreateFromStyle( "default-text")) );
*
BaseHandle CreateFromStyle( const std::string& styleName );
/**
+ * @brief Creates an object from the style templates with user defined constants
+ *
+ * e.g.
+ * PropertyValueMap map;
+ * map["IMAGE_DIR"] = "/usr/share/images"; // replaces '{IMAGE_DIR} in the template
+ * mActor.Add( Actor::DownCast(builder.CreateFromStyle( "default-image", map) ) );
+ *
+ * @pre The Builder has been initialized.
+ * @pre Preconditions have been met for creating dali objects ie Images, Actors etc
+ * @pre The styleName has been loaded from the styles section of the data representation
+ * and contains 'type' property used to create the object.
+ * @pre The map contains all the constant expansions in the style template
+ * @param styleName The set of styles/properties to set on the handle object.
+ * @param map The user defined constants used in style template expansion.
+ * @returns The base handle of the created object
+ */
+ BaseHandle CreateFromStyle( const std::string& styleName, const PropertyValueMap& map );
+
+ /**
* Apply a style (a collection of properties) to an actor.
* @pre The Builder has been initialized.
* @pre Preconditions have been met for creating dali objects ie Images, Actors etc