+ mSignalConnectors.push_back( ConnectionPair( signalName, function ) );
+ }
+ else
+ {
+ DALI_LOG_WARNING("Signal name already exists in TypeRegistry Type for signal connector function\n", signalName.c_str());
+ }
+ }
+}
+
+void TypeInfo::AddProperty( const std::string& name, Property::Index index, Property::Type type, Dali::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc )
+{
+ // The setter can be empty as a property can be read-only.
+
+ if ( NULL == getFunc )
+ {
+ DALI_ASSERT_ALWAYS( ! "GetProperty Function is empty" );
+ }
+ else
+ {
+ RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+ PairFinder< Property::Index, RegisteredPropertyPair>(index) );
+
+ if ( iter == mRegisteredProperties.end() )
+ {
+ mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, setFunc, getFunc, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
+ }
+ else
+ {
+ DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
+ }
+ }
+}
+
+void TypeInfo::AddProperty( const std::string& name, Property::Index index, Property::Type type, Dali::CSharpTypeInfo::SetPropertyFunction setFunc, Dali::CSharpTypeInfo::GetPropertyFunction getFunc)
+{
+
+ // The setter can be empty as a property can be read-only.
+
+ if ( NULL == getFunc )
+ {
+ DALI_ASSERT_ALWAYS( ! "GetProperty Function is empty" );
+ }
+ else
+ {
+ RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+ PairFinder< Property::Index, RegisteredPropertyPair>(index) );
+
+ if ( iter == mRegisteredProperties.end() )
+ {
+ mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, setFunc, getFunc, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
+ }
+ else
+ {
+ DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
+ }
+ }
+
+}
+
+
+void TypeInfo::AddAnimatableProperty( const std::string& name, Property::Index index, Property::Type type )
+{
+ RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+ PairFinder< Property::Index, RegisteredPropertyPair>(index) );
+
+ if ( iter == mRegisteredProperties.end() )
+ {
+ mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
+ }
+ else
+ {
+ DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
+ }
+}
+
+void TypeInfo::AddAnimatableProperty( const std::string& name, Property::Index index, const Property::Value& defaultValue )
+{
+ RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+ PairFinder< Property::Index, RegisteredPropertyPair>(index) );
+
+ if ( iter == mRegisteredProperties.end() )
+ {
+ mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( defaultValue.GetType(), name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
+ mPropertyDefaultValues.push_back( PropertyDefaultValuePair( index, defaultValue ) );
+ }
+ else
+ {
+ DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
+ }
+}
+
+void TypeInfo::AddAnimatablePropertyComponent( const std::string& name, Property::Index index, Property::Index baseIndex, uint32_t componentIndex )
+{
+ Property::Type type = GetPropertyType( baseIndex );
+ DALI_ASSERT_ALWAYS( ( type == Property::VECTOR2 || type == Property::VECTOR3 || type == Property::VECTOR4 ) && "Base property does not support component" );
+
+ bool success = false;
+
+ RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+ PairFinder< Property::Index, RegisteredPropertyPair>(index) );
+
+ if ( iter == mRegisteredProperties.end() )
+ {
+ iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+ PropertyComponentFinder< RegisteredPropertyPair >( baseIndex, componentIndex ) );
+
+ if ( iter == mRegisteredProperties.end() )
+ {
+ mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, name, baseIndex, componentIndex ) ) );
+ success = true;
+ }
+ }
+
+ DALI_ASSERT_ALWAYS( success && "Property component already registered" );
+}
+
+void TypeInfo::AddChildProperty( const std::string& name, Property::Index index, Property::Type type )
+{
+ RegisteredPropertyContainer::iterator iter = find_if( mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(),
+ PairFinder< Property::Index, RegisteredPropertyPair>(index) );
+
+ if ( iter == mRegisteredChildProperties.end() )
+ {
+ mRegisteredChildProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
+ }
+ else
+ {
+ DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
+ }
+}
+
+uint32_t TypeInfo::GetPropertyCount() const
+{
+ uint32_t count = mDefaultPropertyCount + static_cast<uint32_t>( mRegisteredProperties.size() );
+
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ count += mBaseType->GetPropertyCount();
+ }
+
+ return count;
+}
+
+Property::Index TypeInfo::GetPropertyIndex( const std::string& name ) const
+{
+ Property::Index index = Property::INVALID_INDEX;
+ bool found = false;
+
+ // check default properties
+ if( mDefaultProperties )
+ {
+ for( Property::Index tableIndex = 0; tableIndex < mDefaultPropertyCount; ++tableIndex )
+ {
+ if( 0 == name.compare( mDefaultProperties[ tableIndex ].name ) )
+ {
+ index = mDefaultProperties[ tableIndex ].enumIndex;
+ found = true;
+ break;
+ }
+ }
+ }
+ if( !found )
+ {
+ // Slow but should not be done that often
+ RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+ PropertyNameFinder< RegisteredPropertyPair >( name ) );
+ if ( iter != mRegisteredProperties.end() )
+ {
+ index = iter->first;
+ }
+ else if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ index = mBaseType->GetPropertyIndex( name );
+ }
+ }
+
+ return index;
+}
+
+Property::Index TypeInfo::GetBasePropertyIndex( Property::Index index ) const
+{
+ Property::Index basePropertyIndex = Property::INVALID_INDEX;
+
+ RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+ PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
+
+ if ( iter != mRegisteredProperties.end() )
+ {
+ basePropertyIndex = iter->second.basePropertyIndex;
+ }
+ else if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ basePropertyIndex = mBaseType->GetBasePropertyIndex( index );
+ }
+
+ return basePropertyIndex;
+}
+
+int TypeInfo::GetComponentIndex( Property::Index index ) const
+{
+ int componentIndex = Property::INVALID_COMPONENT_INDEX;
+
+ RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+ PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
+
+ if ( iter != mRegisteredProperties.end() )
+ {
+ componentIndex = iter->second.componentIndex;
+ }
+ else if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ componentIndex = mBaseType->GetComponentIndex( index );
+ }
+
+ return componentIndex;
+}
+
+Property::Index TypeInfo::GetChildPropertyIndex( const std::string& name ) const
+{
+ Property::Index index = Property::INVALID_INDEX;
+
+ // Slow but should not be done that often
+ RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(),
+ PropertyNameFinder< RegisteredPropertyPair >( name ) );
+
+ if ( iter != mRegisteredChildProperties.end() )
+ {
+ index = iter->first;
+ }
+ else if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ index = mBaseType->GetChildPropertyIndex( name );
+ }
+
+ return index;
+}
+
+const std::string& TypeInfo::GetChildPropertyName( Property::Index index ) const
+{
+ RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(),
+ PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
+
+ if ( iter != mRegisteredChildProperties.end() )
+ {
+ return iter->second.name;
+ }
+
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ return mBaseType->GetChildPropertyName( index );
+ }
+
+ DALI_LOG_ERROR( "Property index %d not found\n", index );
+
+ static std::string empty;
+ return empty;
+}
+
+Property::Type TypeInfo::GetChildPropertyType( Property::Index index ) const
+{
+ Property::Type type( Property::NONE );
+
+ RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(),
+ PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
+
+ if ( iter != mRegisteredChildProperties.end() )
+ {
+ type = iter->second.type;
+ }
+ else if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ type = mBaseType->GetChildPropertyType( index );
+ }
+ else
+ {
+ DALI_LOG_ERROR( "Property index %d not found\n", index );
+ }
+
+ return type;
+}
+
+bool TypeInfo::IsPropertyWritable( Property::Index index ) const
+{
+ bool writable = false;
+ bool found = false;
+
+ // default property?
+ if ( ( index < DEFAULT_PROPERTY_MAX_COUNT ) && mDefaultProperties )
+ {
+ found = GetDefaultPropertyField( mDefaultProperties, mDefaultPropertyCount,index, &Dali::PropertyDetails::writable, writable );
+ }
+ else if( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+ {
+ writable = true; // animatable property is writable
+ found = true;
+ }
+ else
+ {
+ RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+ PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
+ if ( iter != mRegisteredProperties.end() )
+ {
+ writable = iter->second.setFunc ? true : false;
+ found = true;
+ }
+ }
+
+ // if not found, continue to base
+ if( !found )
+ {
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ writable = mBaseType->IsPropertyWritable( index );
+ }
+ else
+ {
+ DALI_LOG_ERROR( "Property index %d not found\n", index );
+ }
+ }
+
+ return writable;
+}
+
+bool TypeInfo::IsPropertyAnimatable( Property::Index index ) const
+{
+ bool animatable = false;
+ bool found = false;
+
+ // default property?
+ if ( ( index < DEFAULT_PROPERTY_MAX_COUNT ) && mDefaultProperties )
+ {
+ found = GetDefaultPropertyField( mDefaultProperties, mDefaultPropertyCount,index, &Dali::PropertyDetails::animatable, animatable );
+ }
+ else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
+ {
+ // Type Registry event-thread only properties are not animatable.
+ animatable = false;
+ found = true;
+ }
+ else if( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+ {
+ animatable = true;
+ found = true;
+ }
+
+ // if not found, continue to base
+ if( !found )
+ {
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ animatable = mBaseType->IsPropertyAnimatable( index );