/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 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.
{
TypeInfo::TypeInfo(const std::string &name, const std::string &baseTypeName, Dali::TypeInfo::CreateFunction creator)
- : mTypeName(name), mBaseTypeName(baseTypeName), mCreate(creator)
+ : mTypeName(name), mBaseTypeName(baseTypeName), mCSharpType(false), mCreate(creator)
+{
+ DALI_ASSERT_ALWAYS(!name.empty() && "Type info construction must have a name");
+ DALI_ASSERT_ALWAYS(!baseTypeName.empty() && "Type info construction must have a base type name");
+}
+
+TypeInfo::TypeInfo(const std::string &name, const std::string &baseTypeName, Dali::CSharpTypeInfo::CreateFunction creator)
+ : mTypeName(name), mBaseTypeName(baseTypeName), mCSharpType(true), mCSharpCreate(creator)
{
DALI_ASSERT_ALWAYS(!name.empty() && "Type info construction must have a name");
DALI_ASSERT_ALWAYS(!baseTypeName.empty() && "Type info construction must have a base type name");
if(mCreate)
{
- ret = mCreate();
+ if ( mCSharpType )
+ {
+ // CSharp currently only registers one create function for all custom controls
+ // it uses the type name to decide which one to create
+ ret = *mCSharpCreate( mTypeName.c_str() );
+ }
+ else
+ {
+ ret = mCreate();
+ }
if ( ret )
{
baseImpl.GetPropertyIndices( indices );
}
- if ( ! mRegisteredProperties.empty() )
+ AppendProperties( indices, mRegisteredProperties );
+}
+
+void TypeInfo::GetChildPropertyIndices( Property::IndexContainer& indices ) const
+{
+ Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
+ if ( base )
+ {
+ const TypeInfo& baseImpl( GetImplementation( base ) );
+ baseImpl.GetChildPropertyIndices( indices );
+ }
+
+ AppendProperties( indices, mRegisteredChildProperties );
+}
+
+/**
+ * Append the indices in RegisteredProperties to the given index container.
+ */
+void TypeInfo::AppendProperties( Dali::Property::IndexContainer& indices,
+ const TypeInfo::RegisteredPropertyContainer& registeredProperties ) const
+{
+ if ( ! registeredProperties.empty() )
{
- indices.Reserve( indices.Size() + mRegisteredProperties.size() );
+ indices.Reserve( indices.Size() + registeredProperties.size() );
- const RegisteredPropertyContainer::const_iterator endIter = mRegisteredProperties.end();
- for ( RegisteredPropertyContainer::const_iterator iter = mRegisteredProperties.begin(); iter != endIter; ++iter )
+ for( auto&& elem : registeredProperties )
{
- indices.PushBack( iter->first );
+ indices.PushBack( elem.first );
}
}
}
}
else
{
- DALI_LOG_WARNING("Action already exists in TypeRegistry Type", actionName.c_str());
+ DALI_LOG_WARNING("Action already exists in TypeRegistry Type\n", actionName.c_str());
}
}
}
}
else
{
- DALI_LOG_WARNING("Signal name already exists in TypeRegistry Type for signal connector function", signalName.c_str());
+ 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::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(),
if ( iter == mRegisteredProperties.end() )
{
- mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, NULL, NULL, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
+ 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
{
if ( iter == mRegisteredProperties.end() )
{
- mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, NULL, NULL, name, baseIndex, componentIndex ) ) );
+ mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, name, baseIndex, componentIndex ) ) );
success = true;
}
}
DALI_ASSERT_ALWAYS( success && "Property component already registered" );
}
-size_t TypeInfo::GetPropertyCount() const
+void TypeInfo::AddChildProperty( const std::string& name, Property::Index index, Property::Type type )
{
- size_t count( mRegisteredProperties.size() );
+ 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 = static_cast<uint32_t>( mRegisteredProperties.size() );
Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
while ( base )
{
const TypeInfo& baseImpl( GetImplementation(base) );
- count += baseImpl.mRegisteredProperties.size();
+ count += static_cast<uint32_t>( baseImpl.mRegisteredProperties.size() );
base = TypeRegistry::Get()->GetTypeInfo( baseImpl.mBaseTypeName );
}
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
+ {
+ Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
+ if ( base )
+ {
+ index = GetImplementation(base).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;
+ }
+
+ Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
+ if ( base )
+ {
+ return GetImplementation(base).GetChildPropertyName( index );
+ }
+
+ DALI_LOG_WARNING("Cannot find property index");
+
+ static std::string emptyString;
+ return emptyString;
+}
+
+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
+ {
+ Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
+ if ( base )
+ {
+ type = GetImplementation(base).GetChildPropertyType( index );
+ }
+ else
+ {
+ DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
+ }
+ }
+
+ return type;
+}
+
bool TypeInfo::IsPropertyWritable( Property::Index index ) const
{
bool writable( false );
if ( iter != mRegisteredProperties.end() )
{
- type = iter->second.type;
+ if( iter->second.componentIndex == Property::INVALID_COMPONENT_INDEX )
+ {
+ type = iter->second.type;
+ }
+ else
+ {
+ // If component index is set, then we should return FLOAT
+ type = Property::FLOAT;
+ }
}
else
{
return type;
}
+Property::Value TypeInfo::GetPropertyDefaultValue( Property::Index index ) const
+{
+ PropertyDefaultValueContainer::const_iterator iter = find_if( mPropertyDefaultValues.begin(), mPropertyDefaultValues.end(),
+ PairFinder< Property::Index, PropertyDefaultValuePair >( index ) );
+ if( iter != mPropertyDefaultValues.end() )
+ {
+ return iter->second;
+ }
+ else
+ {
+ return Property::Value( GetPropertyType( index ) );
+ }
+}
+
void TypeInfo::SetProperty( BaseObject *object, Property::Index index, const Property::Value& value ) const
{
RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
{
if( iter->second.setFunc )
{
- iter->second.setFunc( object, index, value );
+ if( mCSharpType )
+ {
+ // CSharp wants a property name not an index
+ const std::string& name = (iter->second).name;
+
+ iter->second.cSharpSetFunc( object,name.c_str(), const_cast< Property::Value* >(&value) );
+ }
+ else
+ {
+ iter->second.setFunc( object, index, value );
+ }
}
}
else
if ( iter != mRegisteredProperties.end() )
{
DALI_ASSERT_ALWAYS( iter->second.setFunc && "Trying to write to a read-only property" );
- iter->second.setFunc( object, iter->first, value );
+
+ if( mCSharpType )
+ {
+ // CSharp wants a property name not an index
+ iter->second.cSharpSetFunc( object,name.c_str(), const_cast< Property::Value* >(&value ));
+ }
+ else
+ {
+ iter->second.setFunc( object, iter->first, value );
+ }
}
else
{
PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
if( iter != mRegisteredProperties.end() )
{
- // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
- return iter->second.getFunc( const_cast< BaseObject* >( object ), index );
+ if( mCSharpType ) // using csharp property get which returns a pointer to a Property::Value
+ {
+ // CSharp wants a property name not an index
+ // CSharp callback can't return an object by value, it can only return a pointer
+ // CSharp has ownership of the pointer contents, which is fine because we are returning by from this function by value
+ const std::string& name = (iter->second).name;
+
+ return *( iter->second.cSharpGetFunc( const_cast< BaseObject* >( object ), name.c_str()) );
+
+ }
+ else
+ {
+ // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
+ return iter->second.getFunc( const_cast< BaseObject* >( object ), index );
+ }
}
Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
Property::Value TypeInfo::GetProperty( const BaseObject *object, const std::string& name ) const
{
RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
- PropertyNameFinder< RegisteredPropertyPair >( name ) );
+ PropertyNameFinder< RegisteredPropertyPair >( name ) );
+
+
+
if( iter != mRegisteredProperties.end() )
{
- // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
- return iter->second.getFunc( const_cast< BaseObject* >( object ), iter->first );
+ if( mCSharpType ) // using csharp property get which returns a pointer to a Property::Value
+ {
+ // CSharp wants a property name not an index
+ // CSharp callback can't return an object by value, it can only return a pointer
+ // CSharp has ownership of the pointer contents, which is fine because we are returning by from this function by value
+ return *( iter->second.cSharpGetFunc( const_cast< BaseObject* >( object ), name.c_str() ));
+
+ }
+ else
+ {
+ // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
+ return iter->second.getFunc( const_cast< BaseObject* >( object ), iter->first );
+ }
}
Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );