X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fbuilder%2Fbuilder-impl.cpp;h=de3fbe14e119bea994dbe15c677d935bc5d8dcde;hp=fd58ec33e24940e91a52951aa220ddb550e8478c;hb=29d3264d67c7dac9c3e7059140fa7eef3592a823;hpb=fa83ec19c60479f5fb95fee1302881ec51dfe23a diff --git a/dali-toolkit/internal/builder/builder-impl.cpp b/dali-toolkit/internal/builder/builder-impl.cpp index fd58ec3..de3fbe1 100644 --- a/dali-toolkit/internal/builder/builder-impl.cpp +++ b/dali-toolkit/internal/builder/builder-impl.cpp @@ -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. @@ -20,26 +20,30 @@ // EXTERNAL INCLUDES #include -#include #include + #include #include #include #include #include -#include #include -#include +#include +#include #include // INTERNAL INCLUDES #include -#include +#include #include #include #include +#include #include +#include + +#include 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, boost::function quitAction, Dali::Toolkit::Internal::Builder* const builder); -extern Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function quitAction, Dali::Toolkit::Internal::Builder* const builder); -extern Actor SetupActor( const TreeNode& node, Actor& actor, const Replacement& constant ); +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); #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,121 +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 TreeNodeList; +const std::string PROPERTIES = "properties"; +const std::string ANIMATABLE_PROPERTIES = "animatableProperties"; -template -std::string ToString(const T& value) -{ - std::stringstream ss; - ss << value; - return ss.str(); -} - -template <> -std::string ToString(const Rect& value) -{ - std::stringstream ss; - ss << value.x << "," << value.y << "," << value.width << "," << value.height; - return ss.str(); -} +typedef std::vector 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() ? "True" : "False"; - break; - } - case Property::FLOAT: - { - - ret = ToString( value.Get() ); - break; - } - case Property::INTEGER: - { - ret = ToString( value.Get() ); - break; - } - case Property::UNSIGNED_INTEGER: - { - ret = ToString( value.Get() ); - break; - } - case Property::VECTOR2: - { - ret = ToString( value.Get() ); - break; - } - case Property::VECTOR3: - { - ret = ToString( value.Get() ); - break; - } - case Property::VECTOR4: - { - ret = ToString( value.Get() ); - break; - } - case Property::MATRIX3: - { - ret = ToString( value.Get() ); - break; - } - case Property::MATRIX: - { - ret = ToString( value.Get() ); - break; - } - case Property::RECTANGLE: - { - ret = ToString( value.Get< Rect >() ); - break; - } - case Property::ROTATION: - { - break; - } - case Property::STRING: - { - ret = value.Get(); - break; - } - case Property::ARRAY: - { - ret = std::string("Array Size=") + ToString( value.Get().Size() ); - break; - } - case Property::MAP: - { - ret = std::string("Map Size=") + ToString( value.Get().Count() ); - break; - } - case Property::TYPE_COUNT: + if( test.at(0) == '<' ) { - ret = ""; - 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 @@ -203,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) ); @@ -217,22 +131,6 @@ void CollectAllStyles( const TreeNode& stylesCollection, const TreeNode& style, } } -struct QuitAction -{ -public: - QuitAction( Builder& builder ) - : mBuilder( builder ) - { - } - - void operator()(void) - { - mBuilder.EmitQuitSignal(); - } - -private: - Builder& mBuilder; -}; } // namespace anon @@ -243,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; @@ -250,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() ); @@ -340,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 @@ -348,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 ) @@ -358,12 +239,9 @@ void Builder::ApplyProperties( const TreeNode& root, const TreeNode& node, if( actor ) { - SetupActor( node, actor, constant ); - // add signals - QuitAction quitAction( *this ); - SetupSignalAction( mSlotDelegate.GetConnectionTracker(), root, node, actor, quitAction, this ); - SetupPropertyNotification( mSlotDelegate.GetConnectionTracker(), root, node, actor, quitAction, this ); + SetupSignalAction( mSlotDelegate.GetConnectionTracker(), root, node, actor, this ); + SetupPropertyNotification( mSlotDelegate.GetConnectionTracker(), root, node, actor, this ); } } else @@ -572,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) @@ -585,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) @@ -598,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) @@ -611,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) { @@ -628,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 ) @@ -640,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) { @@ -679,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 ); @@ -734,16 +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 propertyMap(Property::MAP); - if( SetPropertyFromNode( *image, Property::MAP, propertyMap, constant ) ) + Dali::Property::Value property(Property::MAP); + if( DeterminePropertyFromNode( *image, Property::MAP, property, constant ) ) { - propertyMap.SetValue(KEYNAME_TYPE, Property::Value(std::string("FrameBufferImage"))); - ret = FrameBufferImage::DownCast( Dali::Scripting::NewImage( propertyMap ) ); - mFrameBufferImageLut[ name ] = ret; + Property::Map* map = property.GetMap(); + + if( map ) + { + (*map)[ KEYNAME_TYPE ] = Property::Value(std::string("FrameBufferImage") ); + ret = FrameBufferImage::DownCast( Dali::Scripting::NewImage( property ) ); + mFrameBufferImageLut[ name ] = ret; + } } } } @@ -773,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); } @@ -815,6 +661,212 @@ Path Builder::GetPath( const std::string& name ) return ret; } +PathConstrainer Builder::GetPathConstrainer( const std::string& name ) +{ + DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded"); + + //Search the pathConstrainer in the LUT + size_t count( mPathConstrainerLut.size() ); + for( size_t i(0); i!=count; ++i ) + { + if( mPathConstrainerLut[i].name == name ) + { + //PathConstrainer has already been created + return mPathConstrainerLut[i].pathConstrainer; + } + } + + //Create a new PathConstrainer + PathConstrainer ret; + if( OptionalChild constrainers = IsChild( *mParser.GetRoot(), "constrainers") ) + { + if( OptionalChild pathConstrainer = IsChild( *constrainers, name ) ) + { + OptionalString constrainerType(IsString(IsChild(*pathConstrainer, "type"))); + if(!constrainerType) + { + DALI_SCRIPT_WARNING("Constrainer type not specified for constrainer '%s'\n", name.c_str() ); + } + else if( *constrainerType == "PathConstrainer") + { + //points property + if( OptionalChild pointsProperty = IsChild( *pathConstrainer, "points") ) + { + Dali::Property::Value points(Property::ARRAY); + if( DeterminePropertyFromNode( *pointsProperty, Property::ARRAY, points ) ) + { + ret = PathConstrainer::New(); + ret.SetProperty( PathConstrainer::Property::POINTS, points); + + //controlPoints property + if( OptionalChild pointsProperty = IsChild( *pathConstrainer, "controlPoints") ) + { + Dali::Property::Value points(Property::ARRAY); + if( DeterminePropertyFromNode( *pointsProperty, Property::ARRAY, points ) ) + { + ret.SetProperty( PathConstrainer::Property::CONTROL_POINTS, points); + } + + //Forward vector + OptionalVector3 forward( IsVector3( IsChild(*pathConstrainer, "forward" ) ) ); + if( forward ) + { + ret.SetProperty( PathConstrainer::Property::FORWARD, *forward); + } + + //Add the new constrainer to the vector of PathConstrainer + PathConstrainerEntry entry = {name,ret}; + mPathConstrainerLut.push_back( entry ); + } + else + { + //Control points not specified + DALI_SCRIPT_WARNING("Control points not specified for pathConstrainer '%s'\n", name.c_str() ); + } + } + } + else + { + //Interpolation points not specified + DALI_SCRIPT_WARNING("Interpolation points not specified for pathConstrainer '%s'\n", name.c_str() ); + } + } + else + { + DALI_SCRIPT_WARNING("Constrainer '%s' is not a PathConstrainer\n", name.c_str() ); + } + } + } + + return ret; +} + +bool Builder::IsPathConstrainer( const std::string& name ) +{ + size_t count( mPathConstrainerLut.size() ); + for( size_t i(0); i!=count; ++i ) + { + if( mPathConstrainerLut[i].name == name ) + { + return true; + } + } + + if( OptionalChild constrainers = IsChild( *mParser.GetRoot(), "constrainers") ) + { + if( OptionalChild constrainer = IsChild( *constrainers, name ) ) + { + OptionalString constrainerType(IsString(IsChild(*constrainer, "type"))); + if(!constrainerType) + { + return false; + } + else + { + return *constrainerType == "PathConstrainer"; + } + } + } + return false; +} + +Dali::LinearConstrainer Builder::GetLinearConstrainer( const std::string& name ) +{ + DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded"); + + //Search the LinearConstrainer in the LUT + size_t count( mLinearConstrainerLut.size() ); + for( size_t i(0); i!=count; ++i ) + { + if( mLinearConstrainerLut[i].name == name ) + { + //LinearConstrainer has already been created + return mLinearConstrainerLut[i].linearConstrainer; + } + } + + //Create a new LinearConstrainer + LinearConstrainer ret; + if( OptionalChild constrainers = IsChild( *mParser.GetRoot(), "constrainers") ) + { + if( OptionalChild linearConstrainer = IsChild( *constrainers, name ) ) + { + OptionalString constrainerType(IsString(IsChild(*linearConstrainer, "type"))); + if(!constrainerType) + { + DALI_SCRIPT_WARNING("Constrainer type not specified for constrainer '%s'\n", name.c_str() ); + } + else if( *constrainerType == "LinearConstrainer") + { + //points property + if( OptionalChild pointsProperty = IsChild( *linearConstrainer, "value") ) + { + Dali::Property::Value points(Property::ARRAY); + if( DeterminePropertyFromNode( *pointsProperty, Property::ARRAY, points ) ) + { + ret = Dali::LinearConstrainer::New(); + ret.SetProperty( LinearConstrainer::Property::VALUE, points); + + //controlPoints property + if( OptionalChild pointsProperty = IsChild( *linearConstrainer, "progress") ) + { + Dali::Property::Value points(Property::ARRAY); + if( DeterminePropertyFromNode( *pointsProperty, Property::ARRAY, points ) ) + { + ret.SetProperty( LinearConstrainer::Property::PROGRESS, points); + } + } + //Add the new constrainer to vector of LinearConstrainer + LinearConstrainerEntry entry = {name,ret}; + mLinearConstrainerLut.push_back( entry ); + } + } + else + { + //Interpolation points not specified + DALI_SCRIPT_WARNING("Values not specified for LinearConstrainer '%s'\n", name.c_str() ); + } + } + else + { + DALI_SCRIPT_WARNING("Constrainer '%s' is not a LinearConstrainer\n", name.c_str() ); + } + } + } + + return ret; +} + +bool Builder::IsLinearConstrainer( const std::string& name ) +{ + // Search the LinearConstrainer in the LUT + size_t count( mLinearConstrainerLut.size() ); + for( size_t i(0); i!=count; ++i ) + { + if( mLinearConstrainerLut[i].name == name ) + { + return true; + } + } + + if( OptionalChild constrainers = IsChild( *mParser.GetRoot(), "constrainers") ) + { + if( OptionalChild constrainer = IsChild( *constrainers, name ) ) + { + OptionalString constrainerType(IsString(IsChild(*constrainer, "type"))); + if(!constrainerType) + { + return false; + } + else + { + return *constrainerType == "LinearConstrainer"; + } + } + } + return false; +} + Toolkit::Builder::BuilderSignalType& Builder::QuitSignal() { return mQuitSignal; @@ -857,7 +909,7 @@ void Builder::AddActors( const std::string §ionName, 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") ) { @@ -919,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 @@ -932,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 { @@ -969,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 ) @@ -1017,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; } } } @@ -1067,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 ) { @@ -1172,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()