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=226883e6af1d9df8f04608a134a7db7a611fdaa7;hp=83572ec83254fff7bf488624bcb6edb5d6fab45f;hb=6bd46a2944d89638f1c1a1c609f72c9348db6abb;hpb=e2eda444afbe82e9591fe198eef339227f90a616 diff --git a/dali-toolkit/internal/builder/builder-impl.cpp b/dali-toolkit/internal/builder/builder-impl.cpp old mode 100755 new mode 100644 index 83572ec..226883e --- a/dali-toolkit/internal/builder/builder-impl.cpp +++ b/dali-toolkit/internal/builder/builder-impl.cpp @@ -25,10 +25,12 @@ #include #include +#include #include #include #include +#include namespace Dali { @@ -38,9 +40,13 @@ namespace Toolkit 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 ); @@ -53,12 +59,160 @@ Integration::Log::Filter* gFilterScript = Integration::Log::Filter::New(Debug:: namespace { +const std::string KEYNAME_STYLES = "styles"; +const std::string KEYNAME_TYPE = "type"; +const std::string KEYNAME_ACTORS = "actors"; +const std::string KEYNAME_SIGNALS = "signals"; +const std::string KEYNAME_NAME = "name"; +const std::string KEYNAME_TEMPLATES = "templates"; +const std::string KEYNAME_INCLUDES = "includes"; + typedef std::vector TreeNodeList; +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(); +} + + +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() ? "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().size() ); + break; + } + case Property::TYPE_COUNT: + { + ret = ""; + break; + } + } + + return ret; +} + +/* + * Recursively collects all stylesin 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 + * styleList The style list to add nodes to apply + */ +void CollectAllStyles( const TreeNode& stylesCollection, const TreeNode& style, TreeNodeList& styleList ) +{ + // style is an array of style names + if( TreeNode::ARRAY == style.GetType() ) + { + for(TreeNode::ConstIterator iter = style.CBegin(); iter != style.CEnd(); ++iter) + { + if( OptionalString styleName = IsString( (*iter).second ) ) + { + if( OptionalChild node = IsChild( stylesCollection, *styleName) ) + { + styleList.push_back( &(*node) ); + + if( OptionalChild subStyle = IsChild( *node, KEYNAME_STYLES ) ) + { + CollectAllStyles( stylesCollection, *subStyle, styleList ); + } + } + } + } + } +} + +} // namespace anon + /* * Sets the handle properties found in the tree node */ -void SetProperties( const TreeNode& node, Handle& handle, Builder& builder ) +void Builder::SetProperties( const TreeNode& node, Handle& handle, const Replacement& constant ) { if( handle ) { @@ -69,7 +223,7 @@ void SetProperties( const TreeNode& node, Handle& handle, Builder& builder ) std::string key( keyChild.first ); // ignore special fields; type,actors,signals - if(key == "type" || key == "actors" || key == "signals") + if(key == KEYNAME_TYPE || key == KEYNAME_ACTORS || key == KEYNAME_SIGNALS || key == KEYNAME_STYLES) { continue; } @@ -83,9 +237,9 @@ void SetProperties( const TreeNode& node, Handle& handle, Builder& builder ) 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 = GetFrameBufferImage(*s, constant); if(fb) { imageActor.SetImage( fb ); @@ -99,10 +253,10 @@ void SetProperties( const TreeNode& node, Handle& handle, Builder& builder ) 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 = GetShaderEffect(*s, constant); actor.SetShaderEffect(e); } else @@ -120,7 +274,7 @@ void SetProperties( const TreeNode& node, Handle& handle, Builder& builder ) 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 @@ -128,7 +282,7 @@ void SetProperties( const TreeNode& node, Handle& handle, Builder& builder ) } 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 ); } @@ -146,109 +300,154 @@ void SetProperties( const TreeNode& node, Handle& handle, Builder& builder ) } } -/* - * Split a string by delimiter - */ -std::vector SplitString(const std::string &s, char delim, std::vector &elems) +// Set properties from node on handle. +void Builder::ApplyProperties( const TreeNode& root, const TreeNode& node, + Dali::Handle& handle, const Replacement& constant ) { - std::stringstream ss(s); - std::string item; - while(std::getline(ss, item, delim)) + if( Actor actor = Actor::DownCast(handle) ) { - elems.push_back(item); - } - return elems; -} + SetProperties( node, actor, constant ); -/* - * Recursively collects all styles listed in a json node 'type' field. (Could be a comma separated list). - * It also returns the first found base typeInfo from the TypeRegistry. This is the concrete object to instance. - * i.e. the type field can name a json style section or a TypeRegistry base type. - */ -void CollectAllStyles( const TreeNode& styles, const std::string& typeStyleString, TreeNodeList& additionalStyles, TypeInfo& typeInfo ) -{ - typedef std::vector StyleNames; - StyleNames styleNames; + if( actor ) + { + SetupActor( node, actor ); - SplitString(typeStyleString, ',', styleNames); + Control control = Control::DownCast(actor); - for(StyleNames::iterator iter = styleNames.begin(); iter != styleNames.end(); ++iter) + if( control ) + { + SetupControl( node, control ); + } + + // add signals + SetupSignalAction( mSlotDelegate.GetConnectionTracker(), root, node, actor ); + + SetupPropertyNotification( mSlotDelegate.GetConnectionTracker(), root, node, actor ); + } + } + else { - const std::string typeName(*iter); + SetProperties( node, handle, constant ); + } +} - OptionalChild style = IsChild(styles, typeName); - if(style) +// Appling by style helper +// use FindChildByName() to apply properties referenced in KEYNAME_ACTORS in the node +void Builder::ApplyStylesByActor( const TreeNode& root, const TreeNode& node, + Dali::Handle& handle, const Replacement& constant ) +{ + if( Dali::Actor actor = Dali::Actor::DownCast( handle ) ) + { + if( const TreeNode* actors = node.GetChild( KEYNAME_ACTORS ) ) { - additionalStyles.push_back(&(*style)); - - OptionalString styleType = IsString( IsChild(*style, "type") ); - if( styleType ) - { - CollectAllStyles(styles, *styleType, additionalStyles, typeInfo); - } - else + // in a style the actor subtree properties referenced by actor name + for( TreeConstIter iter = actors->CBegin(); iter != actors->CEnd(); ++iter ) { - if(!typeInfo) + Dali::Actor foundActor; + + if( (*iter).first ) + { + foundActor = actor.FindChildByName( (*iter).first ); + } + + if( !foundActor ) + { + // debug log cannot find searched for actor +#if defined(DEBUG_ENABLED) + DALI_SCRIPT_VERBOSE("Cannot find actor in style application '%s'\n", (*iter).first); +#endif + } + else { - // if its not a style then check for a type but only the first found - typeInfo = TypeRegistry::Get().GetTypeInfo( typeName ); +#if defined(DEBUG_ENABLED) + DALI_SCRIPT_VERBOSE("Styles applied to actor '%s'\n", (*iter).first); +#endif + ApplyProperties( root, (*iter).second, foundActor, constant ); } } } - else - { - DALI_ASSERT_DEBUG(!typeInfo); - typeInfo = TypeRegistry::Get().GetTypeInfo( typeName ); - } } } -/* - * Recursively collects all styles listed in a json node 'type' field. (Could be a comma separated list). - * Adds the given node to the end of the additional styles list. - * It also returns the first found base typeInfo from the TypeRegistry. This is the concrete object to instance. - * i.e. the type field can name a json style section or a TypeRegistry base type. - */ -void CollectAllStyles( const OptionalChild& optionalStyles, const TreeNode& node, TreeNodeList& additionalStyles, TypeInfo& typeInfo ) + +void Builder::ApplyAllStyleProperties( const TreeNode& root, const TreeNode& node, + Dali::Handle& handle, const Replacement& constant ) { - OptionalString type = IsString( IsChild(node, "type") ); + OptionalChild styles = IsChild(root, KEYNAME_STYLES); + OptionalChild style = IsChild(node, KEYNAME_STYLES); - if(!type) - { - DALI_SCRIPT_WARNING("Cannot create style as type section is missing\n"); - } - else + if( styles && style ) { - additionalStyles.push_back(&node); + TreeNodeList additionalStyles; - if( optionalStyles ) + CollectAllStyles( *styles, *style, additionalStyles ); + +#if defined(DEBUG_ENABLED) + for(TreeNode::ConstIterator iter = (*style).CBegin(); iter != (*style).CEnd(); ++iter) { - CollectAllStyles( *optionalStyles, *type, additionalStyles, typeInfo ); + if( OptionalString styleName = IsString( (*iter).second ) ) + { + DALI_SCRIPT_VERBOSE("Style Applied '%s'\n", (*styleName).c_str()); + } } - else +#endif + + // a style may have other styles, which has other styles etc so we apply in reverse by convention. + for(TreeNodeList::reverse_iterator iter = additionalStyles.rbegin(); iter != additionalStyles.rend(); ++iter) { - typeInfo = TypeRegistry::Get().GetTypeInfo( *type ); - } + ApplyProperties( root, *(*iter), handle, constant ); + ApplyStylesByActor( root, *(*iter), handle, constant ); + } } + + // applying given node last + ApplyProperties( root, node, handle, constant ); + + ApplyStylesByActor( root, node, handle, constant ); + } + /* * 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::DoCreate( const TreeNode& root, const TreeNode& node, + Actor parent, const Replacement& replacements ) { BaseHandle baseHandle; - TreeNodeList allStyles; TypeInfo typeInfo; + const TreeNode* templateNode = NULL; + + if( OptionalString typeName = IsString(node, KEYNAME_TYPE) ) + { + typeInfo = TypeRegistry::Get().GetTypeInfo( *typeName ); + + if( !typeInfo ) + { + // a template name is also allowed inplace of the type name + OptionalChild templates = IsChild( root, KEYNAME_TEMPLATES); - CollectAllStyles( optionalStyles, node, allStyles, typeInfo ); + if( templates ) + { + if( OptionalChild isTemplate = IsChild( *templates, *typeName ) ) + { + templateNode = &(*isTemplate); + + if( OptionalString templateTypeName = IsString(*templateNode, KEYNAME_TYPE) ) + { + typeInfo = TypeRegistry::Get().GetTypeInfo( *templateTypeName ); + } + } + } + } + } 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 { @@ -261,7 +460,6 @@ BaseHandle Create( ConnectionTracker* tracker, const OptionalChild& optionalStyl { DALI_SCRIPT_VERBOSE("Create:%s\n", typeInfo.GetName().c_str()); - DALI_SCRIPT_VERBOSE(" %d style sections\n", allStyles.size()); #if defined(DEBUG_ENABLED) if(handle) @@ -281,43 +479,42 @@ BaseHandle Create( ConnectionTracker* tracker, const OptionalChild& optionalStyl } #endif // DEBUG_ENABLED - for(TreeNodeList::reverse_iterator iter = allStyles.rbegin(); iter != allStyles.rend(); ++iter) + if( templateNode ) { - SetProperties( *(*iter), handle, builder ); + ApplyProperties( root, *templateNode, handle, replacements ); - if( actor ) // if we created an actor + if( OptionalChild actors = IsChild( *templateNode, KEYNAME_ACTORS ) ) { - SetupActor( *(*iter), actor); - - if( control ) + for( TreeConstIter iter = (*actors).CBegin(); iter != (*actors).CEnd(); ++iter ) { - SetupControl( *(*iter), control); + DoCreate( root, (*iter).second, actor, replacements ); } + } + } - // add children of all the styles - if( OptionalChild actors = IsChild( *(*iter), "actors" ) ) + ApplyProperties( root, node, handle, replacements ); + + if( actor) + { + // add children of all the styles + if( OptionalChild actors = IsChild( node, KEYNAME_ACTORS ) ) + { + for( TreeConstIter iter = (*actors).CBegin(); iter != (*actors).CEnd(); ++iter ) { - for( TreeConstIter iter = (*actors).CBegin(); iter != (*actors).CEnd(); ++iter ) - { - Create( tracker, optionalStyles, (*iter).second, root, actor, builder ); - } + DoCreate( root, (*iter).second, actor, replacements ); } } - } - if( actor ) - { - // add signals first - SetupSignalAction( tracker, root, node, actor ); - SetupPropertyNotification( tracker, root, node, actor ); + // apply style on top as they need the children to exist + ApplyAllStyleProperties( root, node, actor, replacements ); // then add to parent if( parent ) { parent.Add( actor ); } - } + } else { @@ -329,9 +526,6 @@ BaseHandle Create( ConnectionTracker* tracker, const OptionalChild& optionalStyl } -} // namespace anon - - ActorContainer Builder::GetTopLevelActors() const { // deprecated function. @@ -344,12 +538,12 @@ Animation Builder::GetAnimation( const std::string &name ) const 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) @@ -362,7 +556,7 @@ void Builder::SetupTask( RenderTask& task, const TreeNode& node ) } } - 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) @@ -375,9 +569,9 @@ void Builder::SetupTask( RenderTask& task, const TreeNode& node ) } } - 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 ); @@ -388,7 +582,7 @@ void Builder::SetupTask( RenderTask& task, const TreeNode& node ) } } - 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) { @@ -405,12 +599,16 @@ void Builder::SetupTask( RenderTask& task, const TreeNode& node ) } // other setup is via the property system - SetProperties( node, task, *this ); // @ todo, remove 'source-actor', 'camera-actor'? + SetProperties( node, task, constant ); // @ todo, remove 'source-actor', 'camera-actor'? } void Builder::CreateRenderTask( const std::string &name ) { + DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded"); + + Replacement constant(mReplacementMap); + const Stage& stage = Stage::GetCurrent(); OptionalChild tasks = IsChild(*mParser.GetRoot(), "render-tasks"); @@ -439,21 +637,29 @@ void Builder::CreateRenderTask( const std::string &name ) 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( 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 ) ); @@ -468,7 +674,7 @@ ShaderEffect Builder::GetShaderEffect( const std::string &name ) 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; @@ -482,6 +688,14 @@ ShaderEffect Builder::GetShaderEffect( const std::string &name ) FrameBufferImage Builder::GetFrameBufferImage( const std::string &name ) { + Replacement constant( mReplacementMap ); + return GetFrameBufferImage(name, constant); +} + +FrameBufferImage Builder::GetFrameBufferImage( const std::string &name, const Replacement& constant ) +{ + DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded"); + FrameBufferImage ret; ImageLut::const_iterator iter( mFrameBufferImageLut.find( name ) ); @@ -496,9 +710,9 @@ FrameBufferImage Builder::GetFrameBufferImage( const std::string &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"))); + propertyMap.SetValue(KEYNAME_TYPE, Property::Value(std::string("FrameBufferImage"))); ret = Dali::Scripting::NewImage( propertyMap ); mFrameBufferImageLut[ name ] = ret; } @@ -542,16 +756,19 @@ void Builder::AddActors( Actor toActor ) void Builder::AddActors( const std::string §ionName, Actor toActor ) { - OptionalChild addToStage = IsChild(*mParser.GetRoot(), sectionName); + DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded"); - if( addToStage ) - { - OptionalChild styles = IsChild(*mParser.GetRoot(), "styles"); + PropertyValueMap overrideMap; + Replacement replacements(overrideMap, mReplacementMap); + + OptionalChild add = IsChild(*mParser.GetRoot(), sectionName); - for( TreeNode::ConstIterator iter = (*addToStage).CBegin(); iter != (*addToStage).CEnd(); ++iter ) + if( add ) + { + for( TreeNode::ConstIterator iter = (*add).CBegin(); iter != (*add).CEnd(); ++iter ) { // empty actor adds directly to the stage - BaseHandle baseHandle = Create( mSlotDelegate.GetConnectionTracker(), styles, (*iter).second, *mParser.GetRoot(), Actor(), *this); + BaseHandle baseHandle = DoCreate( *mParser.GetRoot(), (*iter).second, Actor(), replacements ); Actor actor = Actor::DownCast(baseHandle); if(actor) { @@ -571,104 +788,262 @@ void Builder::AddActors( const std::string §ionName, Actor toActor ) } } } - } } -Animation Builder::CreateAnimation( const std::string& animationName ) +Animation Builder::CreateAnimation( const std::string& animationName, const Replacement& replacement, Dali::Actor sourceActor ) { + DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded"); + Animation anim; if( OptionalChild animations = IsChild(*mParser.GetRoot(), "animations") ) { if( OptionalChild animation = IsChild(*animations, animationName) ) { - anim = Dali::Toolkit::Internal::CreateAnimation( *animation ); + anim = Dali::Toolkit::Internal::CreateAnimation( *animation, replacement, sourceActor ); + } + 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 sourceActor ) +{ + Replacement replacement(map, mReplacementMap); + return CreateAnimation( animationName, replacement, sourceActor); +} + +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 sourceActor ) +{ + Replacement replacement( mReplacementMap ); + + return CreateAnimation( animationName, replacement, sourceActor ); +} + +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" ); - if( !mParser.Parse(data) ) + // parser to get constants and includes only + Dali::Toolkit::JsonParser parser = Dali::Toolkit::JsonParser::New(); + + if( !parser.Parse( data ) ) { DALI_LOG_WARNING( "JSON Parse Error:%d:%d:'%s'\n", - mParser.GetErrorLineNumber(), - mParser.GetErrorColumn(), - mParser.GetErrorDescription().c_str() ); + parser.GetErrorLineNumber(), + parser.GetErrorColumn(), + parser.GetErrorDescription().c_str() ); DALI_ASSERT_ALWAYS(!"Cannot parse JSON"); + + } + else + { + // load constant map (allows the user to override the constants in the json after loading) + LoadConstants( *parser.GetRoot(), mReplacementMap ); + + // merge includes + if( OptionalChild includes = IsChild(*parser.GetRoot(), KEYNAME_INCLUDES) ) + { + Replacement replacer( mReplacementMap ); + + for(TreeNode::ConstIterator iter = (*includes).CBegin(); iter != (*includes).CEnd(); ++iter) + { + OptionalString filename = replacer.IsString( (*iter).second ); + + if( filename ) + { +#if defined(DEBUG_ENABLED) + DALI_SCRIPT_VERBOSE("Loading Include '%s'\n", (*filename).c_str()); +#endif + LoadFromString( GetFileContents(*filename) ); + } + } + } + + if( !mParser.Parse( data ) ) + { + DALI_LOG_WARNING( "JSON Parse Error:%d:%d:'%s'\n", + mParser.GetErrorLineNumber(), + mParser.GetErrorColumn(), + mParser.GetErrorDescription().c_str() ); + + DALI_ASSERT_ALWAYS(!"Cannot parse JSON"); + } } DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Cannot parse JSON"); } -void Builder::ApplyStyle( const std::string& styleName, Handle& handle ) +void Builder::AddConstants( const PropertyValueMap& map ) { - OptionalChild styles = IsChild(*mParser.GetRoot(), "styles"); + for(PropertyValueMap::const_iterator iter = map.begin(); iter != map.end(); ++iter) + { + mReplacementMap[ (*iter).first ] = (*iter).second; + } +} - if( styles ) +void Builder::AddConstant( const std::string& key, const Property::Value& value ) +{ + mReplacementMap[key] = value; +} + +const PropertyValueMap& Builder::GetConstants() const +{ + return mReplacementMap; +} + +const Property::Value& Builder::GetConstant( const std::string& key ) const +{ + PropertyValueMap::const_iterator iter = mReplacementMap.find( key ); + if( iter != mReplacementMap.end() ) { - if( OptionalChild style = IsChild(*styles, styleName) ) - { - TreeNodeList allStyles; - TypeInfo typeInfo; + return (*iter).second; + } + else + { + static Property::Value invalid; + return invalid; + } +} - CollectAllStyles( styles, *style, allStyles, typeInfo ); +void Builder::LoadConstants( const TreeNode& root, PropertyValueMap& intoMap ) +{ + Replacement replacer(intoMap); - for(TreeNodeList::reverse_iterator iter = allStyles.rbegin(); iter != allStyles.rend(); ++iter) + if( OptionalChild constants = IsChild(root, "constants") ) + { + for(TreeNode::ConstIterator iter = (*constants).CBegin(); + iter != (*constants).CEnd(); ++iter) + { + Dali::Property::Value property; + if( (*iter).second.GetName() ) { - SetProperties( *style, handle, *this ); +#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()); + } } } - else + } + +#if defined(DEBUG_ENABLED) + PropertyValueMap::const_iterator iter = intoMap.find( "CONFIG_SCRIPT_LOG_LEVEL" ); + if( iter != intoMap.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" ) { - DALI_SCRIPT_WARNING("Could not find style:%s\n", styleName.c_str()); + 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( mReplacementMap ); + ApplyStyle( styleName, handle, replacer ); +} + +void Builder::ApplyStyle( const std::string& styleName, Handle& handle, const Replacement& replacement ) +{ + DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded"); + + OptionalChild styles = IsChild( *mParser.GetRoot(), KEYNAME_STYLES ); + OptionalChild style = IsChild( *styles, styleName ); + + if( styles && style ) + { + ApplyAllStyleProperties( *mParser.GetRoot(), *style, handle, replacement ); } else { - DALI_SCRIPT_WARNING("No style section available for style:%s\n", styleName.c_str()); + DALI_SCRIPT_WARNING("No styles section to create style '%s'\n", styleName.c_str()); } + } -BaseHandle Builder::CreateFromStyle( const std::string& styleName ) +BaseHandle Builder::Create( const std::string& templateName, const PropertyValueMap& map ) { + Replacement replacement( map, mReplacementMap ); + return Create( templateName, replacement ); +} + +BaseHandle Builder::Create( const std::string& templateName, const Replacement& constant ) +{ + DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded"); + BaseHandle baseHandle; - OptionalChild styles = IsChild(*mParser.GetRoot(), "styles"); + OptionalChild templates = IsChild(*mParser.GetRoot(), KEYNAME_TEMPLATES); - if( !styles ) + if( !templates ) { - DALI_SCRIPT_WARNING("No style section found to CreateFromStyle\n"); + DALI_SCRIPT_WARNING("No template section found to CreateFromTemplate\n"); } else { - OptionalChild style = IsChild(*styles, styleName); - if(!style) + OptionalChild childTemplate = IsChild(*templates, templateName); + if(!childTemplate) { - DALI_SCRIPT_WARNING("Style '%s' does not exist in style section\n", styleName.c_str()); + DALI_SCRIPT_WARNING("Template '%s' does not exist in template section\n", templateName.c_str()); } else { - OptionalString type = IsString( IsChild(*style, "type") ); + OptionalString type = constant.IsString( IsChild(*childTemplate, KEYNAME_TYPE) ); if(!type) { - DALI_SCRIPT_WARNING("Cannot create style '%s' as style section is missing 'type'\n", styleName.c_str()); + DALI_SCRIPT_WARNING("Cannot create template '%s' as template section is missing 'type'\n", templateName.c_str()); } else { - baseHandle = Create( mSlotDelegate.GetConnectionTracker(), styles, *style, *mParser.GetRoot(), Actor(), *this ); + baseHandle = DoCreate( *mParser.GetRoot(), *childTemplate, Actor(), constant ); } } } @@ -676,6 +1051,13 @@ BaseHandle Builder::CreateFromStyle( const std::string& styleName ) return baseHandle; } + +BaseHandle Builder::Create( const std::string& templateName ) +{ + Replacement replacement( mReplacementMap ); + return Create( templateName, replacement ); +} + Builder::Builder() : mSlotDelegate( this ) {