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=f7b89e1b249356f06233512b7433e8d5e5afc22f;hb=6b8ba635f15d672e4773fac8d94b2ff2aa58e9b0;hpb=6efdc8474741c1c9f548308b71266996fd98d775 diff --git a/dali-toolkit/internal/builder/builder-impl.cpp b/dali-toolkit/internal/builder/builder-impl.cpp index f7b89e1..de3fbe1 100644 --- a/dali-toolkit/internal/builder/builder-impl.cpp +++ b/dali-toolkit/internal/builder/builder-impl.cpp @@ -21,12 +21,12 @@ // EXTERNAL INCLUDES #include #include + #include #include #include #include #include -#include #include #include #include @@ -39,7 +39,11 @@ #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 void DeterminePropertyFromNode( const TreeNode& node, Property::Value& value ); -extern void DeterminePropertyFromNode( const TreeNode& node, Property::Value& value, const Replacement& replacements ); -extern bool DeterminePropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value ); -extern bool DeterminePropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value, const Replacement& replacements ); extern Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder); extern Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder); -extern Actor SetupActor( const TreeNode& node, Actor& actor, const Replacement& constant ); #if defined(DEBUG_ENABLED) Integration::Log::Filter* gFilterScript = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_SCRIPT"); @@ -76,111 +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::VECTOR2: - { - ret = ToString( value.Get() ); - break; - } - case Property::VECTOR3: + if( test.at(0) == '<' ) { - 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; + 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 @@ -195,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) ); @@ -219,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; @@ -226,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") - { - ImageActor actor = ImageActor::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 ) { - ImageActor actor = ImageActor::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( !DeterminePropertyFromNode( keyChild.second, type, value, constant ) ) + if( ! mapped ) { - // verbose as this might not be a problem - // eg parentOrigin 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() ); @@ -316,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 @@ -324,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 ) @@ -334,8 +239,6 @@ void Builder::ApplyProperties( const TreeNode& root, const TreeNode& node, if( actor ) { - SetupActor( node, actor, constant ); - // add signals SetupSignalAction( mSlotDelegate.GetConnectionTracker(), root, node, actor, this ); SetupPropertyNotification( mSlotDelegate.GetConnectionTracker(), root, node, actor, this ); @@ -653,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(), "shaderEffects") ) - { - if( OptionalChild effect = IsChild( *effects, name ) ) - { - Dali::Property::Value propertyMap(Property::MAP); - if( DeterminePropertyFromNode( *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 ); @@ -972,7 +839,7 @@ Dali::LinearConstrainer Builder::GetLinearConstrainer( const std::string& name ) bool Builder::IsLinearConstrainer( const std::string& name ) { - //Search the LinearConstrainer in the LUT + // Search the LinearConstrainer in the LUT size_t count( mLinearConstrainerLut.size() ); for( size_t i(0); i!=count; ++i ) { @@ -1104,6 +971,124 @@ Animation Builder::CreateAnimation( const std::string& animationName ) return CreateAnimation( animationName, replacement, Dali::Stage::GetCurrent().GetRootLayer() ); } +bool Builder::ConvertChildValue( const TreeNode& mappingRoot, KeyStack& keyStack, Property::Value& child ) +{ + bool result = false; + + switch( child.GetType() ) + { + case Property::STRING: + { + std::string value; + if( child.Get( value ) ) + { + std::string key; + if( GetMappingKey( value, key ) ) + { + // Check key for cycles: + result=true; + for( KeyStack::iterator iter = keyStack.begin() ; iter != keyStack.end(); ++iter ) + { + if( key.compare(*iter) == 0 ) + { + // key is already in stack; stop. + DALI_LOG_WARNING("Detected cycle in stylesheet mapping table:%s\n", key.c_str()); + child = Property::Value(""); + result=false; + break; + } + } + + if( result ) + { + // The following call will overwrite the child with the value + // from the mapping. + RecursePropertyMap( mappingRoot, keyStack, key.c_str(), Property::NONE, child ); + result = true; + } + } + } + break; + } + + case Property::MAP: + { + Property::Map* map = child.GetMap(); + if( map ) + { + for( Property::Map::SizeType i=0; i < map->Count(); ++i ) + { + Property::Value& child = map->GetValue(i); + ConvertChildValue(mappingRoot, keyStack, child); + } + } + break; + } + + case Property::ARRAY: + { + Property::Array* array = child.GetArray(); + if( array ) + { + for( Property::Array::SizeType i=0; i < array->Count(); ++i ) + { + Property::Value& child = array->GetElementAt(i); + ConvertChildValue(mappingRoot, keyStack, child); + } + } + break; + } + + default: + // Ignore other types. + break; + } + + return result; +} + +bool Builder::RecursePropertyMap( const TreeNode& mappingRoot, KeyStack& keyStack, const char* theKey, Property::Type propertyType, Property::Value& value ) +{ + Replacement replacer( mReplacementMap ); + bool result = false; + + keyStack.push_back( theKey ); + + for( TreeNode::ConstIterator iter = mappingRoot.CBegin(); iter != mappingRoot.CEnd(); ++iter ) + { + std::string aKey( (*iter).first ); + if( aKey.compare( theKey ) == 0 ) + { + if( propertyType == Property::NONE ) + { + DeterminePropertyFromNode( (*iter).second, value, replacer ); + result = true; + } + else + { + result = DeterminePropertyFromNode( (*iter).second, propertyType, value, replacer ); + } + + if( result ) + { + ConvertChildValue(mappingRoot, keyStack, value); + } + break; + } + } + keyStack.pop_back(); + + return result; +} + + +bool Builder::GetPropertyMap( const TreeNode& mappingRoot, const char* theKey, Property::Type propertyType, Property::Value& value ) +{ + KeyStack keyStack; + return RecursePropertyMap( mappingRoot, keyStack, theKey, propertyType, value ); +} + + void Builder::LoadFromString( std::string const& data, Dali::Toolkit::Builder::UIFormat format ) { // parser to get constants and includes only @@ -1153,6 +1138,9 @@ void Builder::LoadFromString( std::string const& data, Dali::Toolkit::Builder::U } } + 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"); } @@ -1243,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 ) {