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=a301570ab336ec01dc072b2e759850a42527a9f5;hb=6b8ba635f15d672e4773fac8d94b2ff2aa58e9b0;hpb=af74001e7e61033e86323da5ad079ccbc310680a diff --git a/dali-toolkit/internal/builder/builder-impl.cpp b/dali-toolkit/internal/builder/builder-impl.cpp index a301570..de3fbe1 100644 --- a/dali-toolkit/internal/builder/builder-impl.cpp +++ b/dali-toolkit/internal/builder/builder-impl.cpp @@ -1,35 +1,49 @@ -// -// 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. -// +/* + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * + */ // CLASS HEADER #include // EXTERNAL INCLUDES #include - -// INTERNAL INCLUDES -#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include #include +// INTERNAL INCLUDES #include +#include #include #include #include +#include #include +#include + +#include namespace Dali { @@ -41,15 +55,9 @@ namespace Internal { class Replacement; -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 ); -extern Control SetupControl( const TreeNode& node, Control& actor ); +extern Animation CreateAnimation(const TreeNode& child, const Replacement& replacements, const Dali::Actor searchRoot, Builder* const builder ); +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"); @@ -58,192 +66,129 @@ Integration::Log::Filter* gFilterScript = Integration::Log::Filter::New(Debug:: namespace { -typedef std::vector TreeNodeList; +#define TOKEN_STRING(x) #x -template -std::string ToString(const T& value) -{ - std::stringstream ss; - ss << value; - return ss.str(); -} +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"; +const std::string KEYNAME_MAPPINGS = "mappings"; -template <> -std::string ToString(const Rect& value) -{ - std::stringstream ss; - ss << value.x << "," << value.y << "," << value.width << "," << value.height; - return ss.str(); -} +const std::string PROPERTIES = "properties"; +const std::string ANIMATABLE_PROPERTIES = "animatableProperties"; + +typedef std::vector TreeNodeList; -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: + if( test.at(0) == '<' ) { - ret = value.Get() ? "True" : "False"; - break; + if( test.at(test.length()-1) == '>' ) + { + key = test.substr( 1, test.length()-2 ); + result = true; + } } - case Property::FLOAT: - { + } + return result; +} - 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: +/* + * 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 + * 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) { - ret = ""; - break; + if( OptionalString styleName = IsString( (*iter).second ) ) + { + if( OptionalChild node = IsChildIgnoreCase( stylesCollection, *styleName) ) + { + styleList.push_back( &(*node) ); + + if( OptionalChild subStyle = IsChild( *node, KEYNAME_STYLES ) ) + { + CollectAllStyles( stylesCollection, *subStyle, styleList ); + } + } + } } } - - return ret; } + +} // namespace anon + /* * Sets the handle properties found in the tree node */ -void SetProperties( const TreeNode& node, Handle& handle, Builder& builder, const Replacement& constant ) +void Builder::SetProperties( const TreeNode& node, Handle& handle, const Replacement& constant ) { if( handle ) { + for( TreeNode::ConstIterator iter = node.CBegin(); iter != node.CEnd(); ++iter ) { const TreeNode::KeyNodePair& keyChild = *iter; std::string key( keyChild.first ); - // ignore special fields; type,actors,signals - if(key == "type" || key == "actors" || key == "signals") + // ignore special fields; type,actors,signals,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 = builder.GetFrameBufferImage(*s, constant); - if(fb) - { - imageActor.SetImage( fb ); - } - } - } - } - } + Handle propertyObject( handle ); - // special field 'effect' references the shader effect instances - if(key == "effect") - { - Actor actor = Actor::DownCast(handle); - OptionalString s = constant.IsString( keyChild.second ); - if(actor && s) - { - ShaderEffect e = builder.GetShaderEffect(*s, constant); - actor.SetShaderEffect(e); - } - else - { - DALI_SCRIPT_WARNING("Could not find or set shader effect\n"); - } - - continue; - } - - Property::Index index = handle.GetPropertyIndex(key); + Dali::Property::Index index = propertyObject.GetPropertyIndex( key ); if( Property::INVALID_INDEX != index ) { - Property::Type type = handle.GetPropertyType(index); - + Property::Type type = propertyObject.GetPropertyType(index); Property::Value value; - if( !SetPropertyFromNode( keyChild.second, type, value, constant ) ) + bool mapped = false; + + // if node.value is a mapping, get the property value from the "mappings" table + if( keyChild.second.GetType() == TreeNode::STRING ) + { + std::string mappingKey; + if( GetMappingKey(keyChild.second.GetString(), mappingKey) ) + { + OptionalChild mappingRoot = IsChild( mParser.GetRoot(), KEYNAME_MAPPINGS ); + mapped = GetPropertyMap( *mappingRoot, mappingKey.c_str(), type, value ); + } + } + 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() ); - handle.SetProperty( index, value ); + propertyObject.SetProperty( index, value ); } } else @@ -251,6 +196,10 @@ void SetProperties( const TreeNode& node, Handle& handle, Builder& builder, cons 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 @@ -259,108 +208,161 @@ void SetProperties( const TreeNode& node, Handle& handle, Builder& builder, cons } } -/* - * Split a string by delimiter - */ -std::vector SplitString(const std::string &s, char delim, std::vector &elems) +void Builder::SetCustomProperties( const TreeNode& node, Handle& handle, const Replacement& constant, + const std::string& childName, Property::AccessMode accessMode ) { - std::stringstream ss(s); - std::string item; - while(std::getline(ss, item, delim)) + // Add custom properties + if( OptionalChild customPropertiesChild = IsChild(node, childName) ) { - elems.push_back(item); + 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 ); + } } - return elems; } -/* - * 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 ) +// Set properties from node on handle. +void Builder::ApplyProperties( const TreeNode& root, const TreeNode& node, + Dali::Handle& handle, const Replacement& constant ) { - typedef std::vector StyleNames; - StyleNames styleNames; - - SplitString(typeStyleString, ',', styleNames); - - for(StyleNames::iterator iter = styleNames.begin(); iter != styleNames.end(); ++iter) + if( Actor actor = Actor::DownCast(handle) ) { - const std::string typeName(*iter); + SetProperties( node, actor, constant ); - OptionalChild style = IsChild(styles, typeName); - if(style) + if( actor ) { - additionalStyles.push_back(&(*style)); + // add signals + SetupSignalAction( mSlotDelegate.GetConnectionTracker(), root, node, actor, this ); + SetupPropertyNotification( mSlotDelegate.GetConnectionTracker(), root, node, actor, this ); + } + } + else + { + SetProperties( node, handle, constant ); + } +} - OptionalString styleType = IsString( IsChild(*style, "type") ); - if( styleType ) - { - CollectAllStyles(styles, *styleType, additionalStyles, typeInfo); - } - else +// 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 ) ) + { + // 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 ); + } -} // 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 Builder::Create( const OptionalChild& optionalStyles, const TreeNode& node, const TreeNode& root, Actor parent, - const Replacement& replacements ) +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) { @@ -371,13 +373,11 @@ BaseHandle Builder::Create( const OptionalChild& optionalStyles, const TreeNode& baseHandle = typeInfo.CreateInstance(); Handle handle = Handle::DownCast(baseHandle); Actor actor = Actor::DownCast(handle); - Control control = Control::DownCast(handle); if(handle) { 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) @@ -391,87 +391,49 @@ BaseHandle Builder::Create( const OptionalChild& optionalStyles, const TreeNode& DALI_SCRIPT_VERBOSE(" Is Actor id=%d\n", actor.GetId()); } + Toolkit::Control control = Toolkit::Control::DownCast(handle); if(control) { DALI_SCRIPT_VERBOSE(" Is Control id=%d\n", actor.GetId()); } #endif // DEBUG_ENABLED - for(TreeNodeList::reverse_iterator iter = allStyles.rbegin(); iter != allStyles.rend(); ++iter) + if( templateNode ) { - 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 ); - } + ApplyProperties( root, *templateNode, handle, replacements ); - if( actor ) + if( OptionalChild actors = IsChild( *templateNode, KEYNAME_ACTORS ) ) { - SetupActor( *(*iter), actor); - - if( control ) - { - SetupControl( *(*iter), control); - } - - // add children of all the styles - if( OptionalChild actors = IsChild( *(*iter), "actors" ) ) + for( TreeConstIter iter = (*actors).CBegin(); iter != (*actors).CEnd(); ++iter ) { - for( TreeConstIter iter = (*actors).CBegin(); iter != (*actors).CEnd(); ++iter ) - { - Create( optionalStyles, (*iter).second, root, actor, replacements ); - } + DoCreate( root, (*iter).second, actor, replacements ); } } } if( actor ) { - // add signals first - SetupSignalAction( mSlotDelegate.GetConnectionTracker(), root, node, actor ); + // add children of all the styles + if( OptionalChild actors = IsChild( node, KEYNAME_ACTORS ) ) + { + for( TreeConstIter iter = (*actors).CBegin(); iter != (*actors).CEnd(); ++iter ) + { + DoCreate( root, (*iter).second, actor, replacements ); + } + } - SetupPropertyNotification( mSlotDelegate.GetConnectionTracker(), 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 + { + ApplyProperties( root, node, handle, replacements ); } } else @@ -483,25 +445,12 @@ BaseHandle Builder::Create( const OptionalChild& optionalStyles, const TreeNode& return baseHandle; } - -ActorContainer Builder::GetTopLevelActors() const -{ - // deprecated function. - return ActorContainer(); -} - -Animation Builder::GetAnimation( const std::string &name ) const -{ - // deprecated - return Animation(); -} - void Builder::SetupTask( RenderTask& task, const TreeNode& node, const Replacement& constant ) { 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) @@ -514,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) @@ -527,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) @@ -540,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) { @@ -557,17 +506,18 @@ void Builder::SetupTask( RenderTask& task, const TreeNode& node, const Replaceme } // other setup is via the property system - SetProperties( node, task, *this, constant ); // @ todo, remove 'source-actor', 'camera-actor'? - + SetProperties( node, task, constant ); } 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"); + OptionalChild tasks = IsChild(*mParser.GetRoot(), "renderTasks"); if(tasks) { @@ -606,32 +556,40 @@ void Builder::CreateRenderTask( const std::string &name ) } } -ShaderEffect Builder::GetShaderEffect( const std::string &name) +FrameBufferImage Builder::GetFrameBufferImage( const std::string &name ) { - Replacement constant; - return GetShaderEffect( name, constant ); + Replacement constant( mReplacementMap ); + return GetFrameBufferImage(name, constant); } -ShaderEffect Builder::GetShaderEffect( const std::string &name, const Replacement& constant ) +FrameBufferImage Builder::GetFrameBufferImage( const std::string &name, const Replacement& constant ) { - ShaderEffect ret; + DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded"); + + FrameBufferImage ret; - ShaderEffectLut::const_iterator iter( mShaderEffectLut.find( name ) ); - if( iter != mShaderEffectLut.end() ) + ImageLut::const_iterator iter( mFrameBufferImageLut.find( name ) ); + if( iter != mFrameBufferImageLut.end() ) { ret = iter->second; } else { - if( OptionalChild effects = IsChild( *mParser.GetRoot(), "shader-effects") ) + if( OptionalChild images = IsChild( *mParser.GetRoot(), "frameBufferImages") ) { - if( OptionalChild effect = IsChild( *effects, name ) ) + if( OptionalChild image = IsChild( *images, name ) ) { - Dali::Property::Value propertyMap(Property::MAP); - if( SetPropertyFromNode( *effect, Property::MAP, propertyMap, constant ) ) + Dali::Property::Value property(Property::MAP); + if( DeterminePropertyFromNode( *image, Property::MAP, property, constant ) ) { - ret = Dali::Scripting::NewShaderEffect( propertyMap ); - mShaderEffectLut[ 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; + } } } } @@ -640,64 +598,283 @@ ShaderEffect Builder::GetShaderEffect( const std::string &name, const Replacemen return ret; } -FrameBufferImage Builder::GetFrameBufferImage( const std::string &name ) +Path Builder::GetPath( const std::string& name ) { - Replacement constant; - return GetFrameBufferImage(name, constant); -} + DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded"); -FrameBufferImage Builder::GetFrameBufferImage( const std::string &name, const Replacement& constant ) -{ - FrameBufferImage ret; + Path ret; - ImageLut::const_iterator iter( mFrameBufferImageLut.find( name ) ); - if( iter != mFrameBufferImageLut.end() ) + PathLut::const_iterator iter( mPathLut.find( name ) ); + if( iter != mPathLut.end() ) { ret = iter->second; } else { - if( OptionalChild images = IsChild( *mParser.GetRoot(), "frame-buffer-images") ) + if( OptionalChild paths = IsChild( *mParser.GetRoot(), "paths") ) { - if( OptionalChild image = IsChild( *images, name ) ) + if( OptionalChild path = IsChild( *paths, name ) ) { - Dali::Property::Value propertyMap(Property::MAP); - if( SetPropertyFromNode( *image, Property::MAP, propertyMap, constant ) ) + //points property + if( OptionalChild pointsProperty = IsChild( *path, "points") ) { - propertyMap.SetValue("type", Property::Value(std::string("FrameBufferImage"))); - ret = Dali::Scripting::NewImage( propertyMap ); - mFrameBufferImageLut[ name ] = ret; + Dali::Property::Value points(Property::ARRAY); + if( DeterminePropertyFromNode( *pointsProperty, Property::ARRAY, points ) ) + { + ret = Path::New(); + ret.SetProperty( Path::Property::POINTS, points); + + //controlPoints property + if( OptionalChild pointsProperty = IsChild( *path, "controlPoints") ) + { + Dali::Property::Value points(Property::ARRAY); + if( DeterminePropertyFromNode( *pointsProperty, Property::ARRAY, points ) ) + { + ret.SetProperty( Path::Property::CONTROL_POINTS, points); + } + } + else + { + //Curvature + float curvature(0.25f); + if( OptionalFloat pointsProperty = IsFloat( *path, "curvature") ) + { + curvature = *pointsProperty; + } + ret.GenerateControlPoints(curvature); + } + + //Add the new path to the hash table for paths + mPathLut[ name ] = ret; + } + } + else + { + //Interpolation points not specified + DALI_SCRIPT_WARNING("Interpolation points not specified for path '%s'\n", name.c_str() ); } } + } } return ret; } -Font Builder::GetFont( const std::string& name ) const +PathConstrainer Builder::GetPathConstrainer( const std::string& name ) { - // deprecated function. - Font font; - return font; + 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; } -TextStyle Builder::GetTextStyle( const std::string& name ) const +bool Builder::IsLinearConstrainer( const std::string& name ) { - // deprecated - return TextStyle(); + // 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; } -Image Builder::GetImage( const std::string& name) const +Toolkit::Builder::BuilderSignalType& Builder::QuitSignal() { - // deprecated function. - return Image(); + return mQuitSignal; } -Actor Builder::GetActor( const std::string &name ) const +void Builder::EmitQuitSignal() { - // deprecated function. - return Actor(); + mQuitSignal.Emit(); } void Builder::AddActors( Actor toActor ) @@ -708,19 +885,19 @@ void Builder::AddActors( Actor toActor ) void Builder::AddActors( const std::string §ionName, Actor toActor ) { - PropertyValueMap overrideMap; + DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded"); + + Property::Map overrideMap; Replacement replacements(overrideMap, mReplacementMap); - OptionalChild addToStage = IsChild(*mParser.GetRoot(), sectionName); + OptionalChild add = IsChild(*mParser.GetRoot(), sectionName); - if( addToStage ) + if( add ) { - OptionalChild styles = IsChild(*mParser.GetRoot(), "styles"); - - for( TreeNode::ConstIterator iter = (*addToStage).CBegin(); iter != (*addToStage).CEnd(); ++iter ) + for( TreeNode::ConstIterator iter = (*add).CBegin(); iter != (*add).CEnd(); ++iter ) { // empty actor adds directly to the stage - BaseHandle baseHandle = Create( styles, (*iter).second, *mParser.GetRoot(), Actor(), replacements ); + BaseHandle baseHandle = DoCreate( *mParser.GetRoot(), (*iter).second, Actor(), replacements ); Actor actor = Actor::DownCast(baseHandle); if(actor) { @@ -732,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") ) { @@ -743,15 +920,17 @@ void Builder::AddActors( const std::string §ionName, Actor toActor ) } } -Animation Builder::CreateAnimation( const std::string& animationName, const Replacement& replacement, Dali::Actor searchRoot ) +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, replacement, Stage::GetCurrent().GetRootLayer() ); + anim = Dali::Toolkit::Internal::CreateAnimation( *animation, replacement, sourceActor, this ); } else { @@ -766,65 +945,239 @@ Animation Builder::CreateAnimation( const std::string& animationName, const Repl return anim; } -Animation Builder::CreateAnimation( const std::string& animationName, const PropertyValueMap& map, Dali::Actor searchRoot ) +Animation Builder::CreateAnimation( const std::string& animationName, const Property::Map& map, Dali::Actor sourceActor ) { Replacement replacement(map, mReplacementMap); - return CreateAnimation( animationName, replacement, searchRoot); + return CreateAnimation( animationName, replacement, sourceActor); } -Animation Builder::CreateAnimation( const std::string& animationName, const PropertyValueMap& map ) +Animation Builder::CreateAnimation( const std::string& animationName, const Property::Map& map ) { Replacement replacement(map, mReplacementMap); return CreateAnimation( animationName, replacement, Stage::GetCurrent().GetRootLayer() ); } -Animation Builder::CreateAnimation( const std::string& animationName, Dali::Actor searchRoot ) +Animation Builder::CreateAnimation( const std::string& animationName, Dali::Actor sourceActor ) { Replacement replacement( mReplacementMap ); - return CreateAnimation( animationName, replacement, searchRoot ); + return CreateAnimation( animationName, replacement, sourceActor ); } Animation Builder::CreateAnimation( const std::string& animationName ) { Replacement replacement( mReplacementMap ); + 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 ) { - DALI_ASSERT_ALWAYS( format == Dali::Toolkit::Builder::JSON && "Currently only JSON is supported" ); + // parser to get constants and includes only + Dali::Toolkit::JsonParser parser = Dali::Toolkit::JsonParser::New(); - if( !mParser.Parse(data) ) + 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"); + } + } + + 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 ) +{ + mReplacementMap.Merge( map ); +} - // load constant map (allows the user to override the constants in the json after loading) - LoadConstants(); +void Builder::AddConstant( const std::string& key, const Property::Value& value ) +{ + mReplacementMap[key] = value; +} +const Property::Map& Builder::GetConstants() const +{ + return mReplacementMap; } -void Builder::AddConstants( const PropertyValueMap& map ) +const Property::Value& Builder::GetConstant( const std::string& key ) const { - for(PropertyValueMap::const_iterator iter = map.begin(); iter != map.end(); ++iter) + Property::Value* match = mReplacementMap.Find( key ); + if( match ) + { + return (*match); + } + else { - mReplacementMap[ (*iter).first ] = (*iter).second; + static Property::Value invalid; + return invalid; } } -void Builder::LoadConstants() +void Builder::LoadConstants( const TreeNode& root, Property::Map& intoMap ) { - Replacement replacer(mReplacementMap); + Replacement replacer(intoMap); - if( OptionalChild constants = IsChild(*mParser.GetRoot(), "constants") ) + if( OptionalChild constants = IsChild(root, "constants") ) { for(TreeNode::ConstIterator iter = (*constants).CBegin(); iter != (*constants).CEnd(); ++iter) @@ -835,24 +1188,17 @@ void Builder::LoadConstants() #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()); - } + DeterminePropertyFromNode( (*iter).second, property, replacer ); + intoMap[ (*iter).second.GetName() ] = property; } } } #if defined(DEBUG_ENABLED) - PropertyValueMap::const_iterator iter = mReplacementMap.find( "CONFIG_SCRIPT_LOG_LEVEL" ); - if( iter != mReplacementMap.end() && (*iter).second.GetType() == Property::STRING ) + Property::Value* iter = intoMap.Find( "CONFIG_SCRIPT_LOG_LEVEL" ); + if( iter && iter->GetType() == Property::STRING ) { - std::string logLevel( (*iter).second.Get< std::string >() ); + std::string logLevel( iter->Get< std::string >() ); if( logLevel == "NoLogging" ) { gFilterScript->SetLogLevel( Integration::Log::NoLogging ); @@ -874,112 +1220,68 @@ void Builder::LoadConstants() } -void Builder::ApplyStyle( const std::string& styleName, Handle& handle ) +bool Builder::ApplyStyle( const std::string& styleName, Handle& handle ) { - Replacement replacer; - ApplyStyle( styleName, handle, replacer ); + Replacement replacer( mReplacementMap ); + return ApplyStyle( styleName, handle, replacer ); } -void Builder::ApplyStyle( const std::string& styleName, Handle& handle, const Replacement& replacement ) +bool Builder::ApplyStyle( const std::string& styleName, Handle& handle, const Replacement& replacement ) { - OptionalChild styles = IsChild(*mParser.GetRoot(), "styles"); + DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded"); - if( styles ) - { - if( OptionalChild style = IsChild(*styles, styleName) ) - { - TreeNodeList allStyles; - TypeInfo typeInfo; + OptionalChild styles = IsChild( *mParser.GetRoot(), KEYNAME_STYLES ); - CollectAllStyles( styles, *style, allStyles, typeInfo ); + std::string styleNameLower(styleName); + OptionalChild style = IsChildIgnoreCase( *styles, styleNameLower ); - for(TreeNodeList::reverse_iterator iter = allStyles.rbegin(); iter != allStyles.rend(); ++iter) - { - 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 - { - DALI_SCRIPT_WARNING("Could not find style:%s\n", styleName.c_str()); - } + if( styles && style ) + { + ApplyAllStyleProperties( *mParser.GetRoot(), *style, handle, replacement ); + return true; } else { - DALI_SCRIPT_WARNING("No style section available for style:%s\n", styleName.c_str()); + return false; } } -BaseHandle Builder::CreateFromStyle( const std::string& styleName, const PropertyValueMap& map ) +BaseHandle Builder::Create( const std::string& templateName, const Property::Map& map ) { Replacement replacement( map, mReplacementMap ); - return CreateFromStyle( styleName, replacement ); + return Create( templateName, replacement ); } -BaseHandle Builder::CreateFromStyle( const std::string& styleName, const Replacement& constant ) +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 = constant.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( styles, *style, *mParser.GetRoot(), Actor(), constant ); + baseHandle = DoCreate( *mParser.GetRoot(), *childTemplate, Actor(), constant ); } } } @@ -987,18 +1289,63 @@ BaseHandle Builder::CreateFromStyle( const std::string& styleName, const Replace return baseHandle; } +BaseHandle Builder::CreateFromJson( const std::string& json ) +{ + BaseHandle ret; + + // merge in new template, hoping no one else has one named '@temp@' + std::string newTemplate = + std::string("{\"templates\":{\"@temp@\":") + \ + json + \ + std::string("}}"); -BaseHandle Builder::CreateFromStyle( const std::string& styleName ) + if( mParser.Parse(newTemplate) ) + { + Replacement replacement( mReplacementMap ); + ret = Create( "@temp@", replacement ); + } + + return ret; +} + +bool Builder::ApplyFromJson( Handle& handle, const std::string& json ) { - PropertyValueMap overrideMap; - Replacement replacement( overrideMap, mReplacementMap ); - return CreateFromStyle( styleName, replacement ); + bool ret = false; + + // merge new style, hoping no one else has one named '@temp@' + std::string newStyle = + std::string("{\"styles\":{\"@temp@\":") + \ + json + \ + std::string("}}"); + + if( mParser.Parse(newStyle) ) + { + Replacement replacement( mReplacementMap ); + ret = ApplyStyle( "@temp@", handle, replacement ); + } + + return ret; +} + + +BaseHandle Builder::Create( const std::string& templateName ) +{ + Replacement replacement( mReplacementMap ); + return Create( templateName, replacement ); } 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()