/*
- * Copyright (c) 2014 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.
using std::find_if;
+namespace Dali
+{
+
+namespace Internal
+{
+
namespace
{
template <typename T>
struct PropertyNameFinder
{
- PropertyNameFinder( const std::string& find )
- : mFind( find )
+ PropertyNameFinder(ConstString find)
+ : mFind(find)
{
}
}
private:
-
- const std::string& mFind;
+ ConstString mFind;
};
-} // namespace anon
+/**
+ * Functor to find a matching property component index
+ */
+template <typename T>
+struct PropertyComponentFinder
+{
+ PropertyComponentFinder( Property::Index basePropertyIndex, const int find )
+ : mBasePropertyIndex( basePropertyIndex ),
+ mFind( find )
+ {
+ }
-namespace Dali
+ bool operator()(const T &p) const
+ {
+ return ( p.second.basePropertyIndex == mBasePropertyIndex && p.second.componentIndex == mFind );
+ }
+
+private:
+
+ Property::Index mBasePropertyIndex;
+ const int mFind;
+};
+
+/**
+ * Helper function to find the right default property with given index and return the desired detail of it
+ */
+template< typename Parameter, typename Member >
+inline bool GetDefaultPropertyField( const Dali::PropertyDetails* propertyTable, Property::Index count, Property::Index index, Member member, Parameter& parameter )
{
+ bool found = false;
+ // is index inside this table (bigger than first index but smaller than first + count)
+ if( ( index >= propertyTable->enumIndex ) && ( index < ( propertyTable->enumIndex + count ) ) )
+ {
+ // return the match. we're assuming here that there is no gaps between the indices in a table
+ parameter = propertyTable[ index - propertyTable->enumIndex ].*member;
+ found = true;
+ }
+ // should never really get here
+ return found;
+}
-namespace Internal
+// static pointer value to mark that a base class address has not been resolved
+// 0x01 is not a valid pointer but used here to differentiate from nullptr
+// unfortunately it cannot be constexpr as C++ does not allow them to be initialised with reinterpret_cast
+Internal::TypeInfo* const UNRESOLVED = reinterpret_cast<Internal::TypeInfo*>( 0x1 );
+
+/**
+ * Helper function to resolve and return the pointer to the base type info
+ * Not a member function to avoid having to #include additional headers and to make sure this gets inlined inside this cpp
+ * @param[in/out] baseType pointer to resolve and set
+ * @param[in] typeRegistry reference to the type registry
+ * @param[in] baseTypeName string name of the base type
+ * @return true is base type exists
+ */
+inline bool GetBaseType( Internal::TypeInfo*& baseType, TypeRegistry& typeRegistry, const std::string& baseTypeName )
{
+ // if greater than unresolved means we have a base type, null means no base
+ bool baseExists = ( baseType > UNRESOLVED );
+ // base only needs to be resolved once
+ if( UNRESOLVED == baseType )
+ {
+ TypeRegistry::TypeInfoPointer base = typeRegistry.GetTypeInfo( baseTypeName );
+ if( base )
+ {
+ baseType = base.Get(); // dont pass ownership, just return raw pointer
+ baseExists = true;
+ }
+ else
+ {
+ // no type info found so assuming no base as all type registration is done in startup for now
+ baseType = nullptr;
+ }
+ }
+ return baseExists;
+}
+
+} // unnamed namespace
-TypeInfo::TypeInfo(const std::string &name, const std::string &baseTypeName, Dali::TypeInfo::CreateFunction creator)
- : mTypeName(name), mBaseTypeName(baseTypeName), mCreate(creator)
+TypeInfo::TypeInfo( const std::string &name, const std::string &baseTypeName, Dali::TypeInfo::CreateFunction creator,
+ const Dali::PropertyDetails* defaultProperties, Property::Index defaultPropertyCount )
+: mTypeRegistry( *TypeRegistry::Get() ), mBaseType( UNRESOLVED ),
+ mTypeName( name ), mBaseTypeName( baseTypeName ), mCreate( creator ), mDefaultProperties( defaultProperties ),
+ mDefaultPropertyCount( defaultPropertyCount ), mCSharpType( false )
{
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()
+TypeInfo::TypeInfo(const std::string &name, const std::string &baseTypeName, Dali::CSharpTypeInfo::CreateFunction creator)
+: mTypeRegistry( *TypeRegistry::Get() ), mBaseType( UNRESOLVED ),
+ mTypeName( name ), mBaseTypeName( baseTypeName ), mCSharpCreate( creator ), mCSharpType( true )
{
+ 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() = default;
+
BaseHandle TypeInfo::CreateInstance() const
{
BaseHandle ret;
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 )
{
return ret;
}
-bool TypeInfo::DoActionTo(BaseObject *object, const std::string &actionName, const std::vector<Property::Value> &properties)
+bool TypeInfo::DoActionTo(BaseObject *object, const std::string &actionName, const Property::Map &properties)
{
bool done = false;
{
done = (iter->second)(object, actionName, properties);
}
- else
- {
- DALI_LOG_WARNING("Type '%s' cannot do action '%s'\n", mTypeName.c_str(), actionName.c_str());
- }
- if(!done)
+ if( !done )
{
- Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
- while( base )
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
{
- done = GetImplementation(base).DoActionTo(object, actionName, properties);
- if( done )
- {
- break;
- }
- base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
+ // call base type recursively
+ done = mBaseType->DoActionTo( object, actionName, properties );
}
}
connected = (iter->second)( object, connectionTracker, signalName, functor );
}
+ if( !connected )
+ {
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ connected = mBaseType->ConnectSignal( object, connectionTracker, signalName, functor );
+ }
+ }
+
return connected;
}
return mCreate;
}
-void TypeInfo::GetActions( Dali::TypeInfo::NameContainer& ret ) const
+uint32_t TypeInfo::GetActionCount() const
{
- for(ActionContainer::const_iterator iter = mActions.begin(); iter != mActions.end(); ++iter)
- {
- ret.push_back(iter->first);
- }
+ uint32_t count = static_cast<uint32_t>( mActions.size() );
- Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
- while( base )
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
{
- for(ActionContainer::const_iterator iter = GetImplementation(base).mActions.begin();
- iter != GetImplementation(base).mActions.end(); ++iter)
- {
- ret.push_back(iter->first);
- }
-
- base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
+ // call base type recursively
+ count += mBaseType->GetActionCount();
}
+
+ return count;
}
-void TypeInfo::GetSignals(Dali::TypeInfo::NameContainer& ret) const
+std::string TypeInfo::GetActionName( uint32_t index ) const
{
- for(ConnectorContainer::const_iterator iter = mSignalConnectors.begin(); iter != mSignalConnectors.end(); ++iter)
+ std::string name;
+ const uint32_t count = static_cast<uint32_t>( mActions.size() );
+
+ if( index < count )
{
- ret.push_back(iter->first);
+ name = mActions[index].first;
}
-
- Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
- while( base )
+ else
{
- for(ConnectorContainer::const_iterator iter = GetImplementation(base).mSignalConnectors.begin();
- iter != GetImplementation(base).mSignalConnectors.end(); ++iter)
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
{
- ret.push_back(iter->first);
+ // call base type recursively
+ return mBaseType->GetActionName( index - count );
}
-
- base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
}
+
+ return name;
}
-void TypeInfo::GetProperties( Dali::TypeInfo::NameContainer& ret ) const
+uint32_t TypeInfo::GetSignalCount() const
{
- Property::IndexContainer indices;
+ uint32_t count = static_cast<uint32_t>( mSignalConnectors.size() );
+
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ count += mBaseType->GetSignalCount();
+ }
- GetPropertyIndices(indices);
+ return count;
+}
- ret.reserve(indices.size());
+std::string TypeInfo::GetSignalName( uint32_t index ) const
+{
+ std::string name;
+ const uint32_t count = static_cast<uint32_t>( mSignalConnectors.size() );
- for(Property::IndexContainer::iterator iter = indices.begin(); iter != indices.end(); ++iter)
+ if( index < count )
+ {
+ name = mSignalConnectors[index].first;
+ }
+ else
{
- const std::string& name = GetPropertyName( *iter );
- if(name.size())
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
{
- ret.push_back( name );
+ // call base type recursively
+ return mBaseType->GetSignalName( index - count );
}
- else
+ }
+
+ return name;
+}
+
+void TypeInfo::GetPropertyIndices( Property::IndexContainer& indices ) const
+{
+ // Default Properties
+ if( mDefaultProperties )
+ {
+ indices.Reserve( indices.Size() + mDefaultPropertyCount );
+ for( Property::Index index = 0; index < mDefaultPropertyCount; ++index )
{
- DALI_LOG_WARNING("Property had no name\n");
+ indices.PushBack( mDefaultProperties[ index ].enumIndex );
}
}
+
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ mBaseType->GetPropertyIndices( indices );
+ }
+
+ AppendProperties( indices, mRegisteredProperties );
}
-void TypeInfo::GetPropertyIndices( Property::IndexContainer& indices ) const
+void TypeInfo::GetChildPropertyIndices( Property::IndexContainer& indices ) const
{
- Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
- if ( base )
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
{
- const TypeInfo& baseImpl( GetImplementation( base ) );
- baseImpl.GetPropertyIndices( indices );
+ // call base type recursively
+ mBaseType->GetChildPropertyIndices( indices );
}
- if ( ! mRegisteredProperties.empty() )
+ 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.push_back( iter->first );
+ indices.PushBack( elem.first );
}
}
}
-const std::string& TypeInfo::GetPropertyName( Property::Index index ) const
+std::string_view TypeInfo::GetRegisteredPropertyName(Property::Index index) const
{
RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
-
if ( iter != mRegisteredProperties.end() )
{
- return iter->second.name;
+ return iter->second.name.GetStringView();
+ }
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ return mBaseType->GetRegisteredPropertyName( index );
}
+ static std::string empty;
+ return empty;
+}
- Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
- if ( base )
+std::string_view TypeInfo::GetPropertyName(Property::Index index) const
+{
+ std::string_view propertyName;
+ // default or custom
+ if ( mDefaultProperties && ( index < DEFAULT_PROPERTY_MAX_COUNT ) )
{
- return GetImplementation(base).GetPropertyName( index );
+ std::string_view name;
+ if( GetDefaultPropertyField( mDefaultProperties, mDefaultPropertyCount,index, &Dali::PropertyDetails::name, name ) )
+ {
+ propertyName = name;
+ }
+ }
+ else
+ {
+ RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+ PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
+ if ( iter != mRegisteredProperties.end() )
+ {
+ return iter->second.name.GetStringView();
+ }
+ }
+ // if not our property, go to parent
+ if( propertyName.empty() )
+ {
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ return mBaseType->GetPropertyName( index );
+ }
}
- DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
+ return propertyName;
}
-void TypeInfo::AddActionFunction( const std::string &actionName, Dali::TypeInfo::ActionFunction function )
+void TypeInfo::AddActionFunction(std::string actionName, Dali::TypeInfo::ActionFunction function)
{
- if( NULL == function)
+ if( nullptr == function)
{
DALI_LOG_WARNING("Action function is empty\n");
}
if( iter == mActions.end() )
{
- mActions.push_back( ActionPair( actionName, function ) );
+ mActions.push_back(ActionPair(std::move(actionName), function));
}
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());
}
}
}
-void TypeInfo::AddConnectorFunction( const std::string& signalName, Dali::TypeInfo::SignalConnectorFunction function )
+void TypeInfo::AddConnectorFunction(std::string signalName, Dali::TypeInfo::SignalConnectorFunction function)
{
- if( NULL == function)
+ if( nullptr == function)
{
DALI_LOG_WARNING("Connector function is empty\n");
}
if( iter == mSignalConnectors.end() )
{
- mSignalConnectors.push_back( ConnectionPair( signalName, function ) );
+ mSignalConnectors.push_back(ConnectionPair(std::move(signalName), function));
}
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::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc )
+void TypeInfo::AddProperty(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 )
+ if ( nullptr == getFunc )
{
DALI_ASSERT_ALWAYS( ! "GetProperty Function is empty" );
}
if ( iter == mRegisteredProperties.end() )
{
- mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, setFunc, getFunc, name ) ) );
+ mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, setFunc, getFunc, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
}
else
{
}
}
-unsigned int TypeInfo::GetPropertyCount() const
+void TypeInfo::AddProperty(std::string name, Property::Index index, Property::Type type, Dali::CSharpTypeInfo::SetPropertyFunction setFunc, Dali::CSharpTypeInfo::GetPropertyFunction getFunc)
{
- unsigned int count( mRegisteredProperties.size() );
- Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
- while ( base )
+ // The setter can be empty as a property can be read-only.
+
+ if ( nullptr == getFunc )
{
- const TypeInfo& baseImpl( GetImplementation(base) );
- count += baseImpl.mRegisteredProperties.size();
- base = TypeRegistry::Get()->GetTypeInfo( baseImpl.mBaseTypeName );
+ 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, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
+ }
+ else
+ {
+ DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
+ }
}
- return count;
}
-Property::Index TypeInfo::GetPropertyIndex( const std::string& name ) const
+void TypeInfo::AddAnimatableProperty(std::string name, Property::Index index, Property::Type type)
{
- Property::Index index = Property::INVALID_INDEX;
+ RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+ PairFinder< Property::Index, RegisteredPropertyPair>(index) );
- // 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() )
+ {
+ mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
+ }
+ else
+ {
+ DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
+ }
+}
- if ( iter != mRegisteredProperties.end() )
+void TypeInfo::AddAnimatableProperty(std::string name, Property::Index index, Property::Value defaultValue)
+{
+ RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+ PairFinder< Property::Index, RegisteredPropertyPair>(index) );
+
+ if ( iter == mRegisteredProperties.end() )
{
- index = iter->first;
+ mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(defaultValue.GetType(), ConstString(name), Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX)));
+ mPropertyDefaultValues.push_back(PropertyDefaultValuePair(index, std::move(defaultValue)));
}
else
{
- Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
- if ( base )
+ DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
+ }
+}
+
+void TypeInfo::AddAnimatablePropertyComponent(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() )
{
- index = GetImplementation(base).GetPropertyIndex( name );
+ mRegisteredProperties.push_back(RegisteredPropertyPair(index, RegisteredProperty(type, ConstString(name), baseIndex, componentIndex)));
+ success = true;
+ }
+ }
+
+ DALI_ASSERT_ALWAYS( success && "Property component already registered" );
+}
+
+void TypeInfo::AddChildProperty(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, ConstString(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(ConstString name) const
+{
+ Property::Index index = Property::INVALID_INDEX;
+ bool found = false;
+
+ // check default properties
+ if( mDefaultProperties )
+ {
+ auto stringView = name.GetStringView();
+ for( Property::Index tableIndex = 0; tableIndex < mDefaultPropertyCount; ++tableIndex )
+ {
+ if(mDefaultProperties[tableIndex].name == stringView)
+ {
+ 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;
}
-bool TypeInfo::IsPropertyWritable( Property::Index index ) const
+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;
+}
+
+int32_t TypeInfo::GetComponentIndex( Property::Index index ) const
{
- bool writable( false );
+ 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() )
{
- writable = iter->second.setFunc ? true : false;
+ componentIndex = iter->second.componentIndex;
+ }
+ else if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ componentIndex = mBaseType->GetComponentIndex( index );
+ }
+
+ return componentIndex;
+}
+
+Property::Index TypeInfo::GetChildPropertyIndex(ConstString 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;
+}
+
+std::string_view 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.GetStringView();
+ }
+
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ return mBaseType->GetChildPropertyName( index );
+ }
+
+ DALI_LOG_ERROR( "Property index %d not found\n", index );
+
+ return {};
+}
+
+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::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
- if ( base )
+ 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 ) )
{
- writable = GetImplementation(base).IsPropertyWritable( index );
+ // call base type recursively
+ writable = mBaseType->IsPropertyWritable( index );
}
else
{
- DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
+ DALI_LOG_ERROR( "Property index %d not found\n", index );
}
}
return writable;
}
-Property::Type TypeInfo::GetPropertyType( Property::Index index ) const
+bool TypeInfo::IsPropertyAnimatable( Property::Index index ) const
{
- Property::Type type( Property::NONE );
+ bool animatable = false;
+ bool found = false;
- RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
- PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
-
- if ( iter != mRegisteredProperties.end() )
+ // default property?
+ if ( ( index < DEFAULT_PROPERTY_MAX_COUNT ) && mDefaultProperties )
{
- type = iter->second.type;
+ found = GetDefaultPropertyField( mDefaultProperties, mDefaultPropertyCount,index, &Dali::PropertyDetails::animatable, animatable );
}
- else
+ 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 )
{
- Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
- if ( base )
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
{
- type = GetImplementation(base).GetPropertyType( index );
+ // call base type recursively
+ animatable = mBaseType->IsPropertyAnimatable( index );
}
else
{
- DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
+ DALI_LOG_ERROR( "Property index %d not found\n", index );
}
}
- return type;
+ return animatable;
}
-void TypeInfo::SetProperty( BaseObject *object, Property::Index index, const Property::Value& value ) const
+bool TypeInfo::IsPropertyAConstraintInput( Property::Index index ) const
{
- RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
- PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
- if ( iter != mRegisteredProperties.end() )
+ bool constraintInput = false;
+ bool found = false;
+
+ // default property?
+ if ( ( index < DEFAULT_PROPERTY_MAX_COUNT ) && mDefaultProperties )
{
- if( iter->second.setFunc )
+ found = GetDefaultPropertyField( mDefaultProperties, mDefaultPropertyCount,index, &Dali::PropertyDetails::constraintInput, constraintInput );
+ }
+ else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
+ {
+ // Type Registry event-thread only properties cannot be used as constraint input
+ constraintInput = false;
+ found = true;
+ }
+ else if( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+ {
+ constraintInput = true;
+ found = true;
+ }
+
+ // if not found, continue to base
+ if( !found )
+ {
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
{
- iter->second.setFunc( object, index, value );
+ // call base type recursively
+ constraintInput = mBaseType->IsPropertyAConstraintInput( index );
}
+ else
+ {
+ DALI_LOG_ERROR( "Property index %d not found\n", index );
+ }
+ }
+
+ return constraintInput;
+}
+
+
+Property::Type TypeInfo::GetPropertyType( Property::Index index ) const
+{
+ Property::Type type( Property::NONE );
+ bool found = false;
+
+ // default property?
+ if ( ( index < DEFAULT_PROPERTY_MAX_COUNT ) && mDefaultProperties )
+ {
+ found = GetDefaultPropertyField( mDefaultProperties, mDefaultPropertyCount,index, &Dali::PropertyDetails::type, type );
}
else
{
- Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
- if ( base )
+ RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+ PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
+
+ if ( iter != mRegisteredProperties.end() )
{
- GetImplementation(base).SetProperty( object, index, value );
+ if( iter->second.componentIndex == Property::INVALID_COMPONENT_INDEX )
+ {
+ type = iter->second.type;
+ found = true;
+ }
+ else
+ {
+ // If component index is set, then we should return FLOAT
+ type = Property::FLOAT;
+ found = true;
+ }
+ }
+ }
+
+ if( !found )
+ {
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ type = mBaseType->GetPropertyType( index );
}
else
{
- DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
+ DALI_LOG_ERROR( "Property index %d not found\n", index );
}
}
+
+ return type;
}
-void TypeInfo::SetProperty( BaseObject *object, const std::string& name, const Property::Value& value ) const
+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;
+ }
+ // we didn't have a value so ask base
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ return mBaseType->GetPropertyDefaultValue( index );
+ }
+ return Property::Value(); // return none
+}
+
+void TypeInfo::SetProperty(BaseObject* object, Property::Index index, Property::Value value) const
{
RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
- PropertyNameFinder< RegisteredPropertyPair >( name ) );
+ PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
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( iter->second.setFunc )
+ {
+ if( mCSharpType )
+ {
+ // CSharp wants a property name not an index
+ auto name = (iter->second).name;
+
+ iter->second.cSharpSetFunc(object, name.GetCString(), const_cast<Property::Value*>(&value));
+ }
+ else
+ {
+ iter->second.setFunc(object, index, std::move(value));
+ }
+ }
+ }
+ else if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ mBaseType->SetProperty(object, index, std::move(value));
}
else
{
- Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
- if ( base )
+ DALI_LOG_ERROR( "Property index %d not found\n", index );
+ }
+}
+
+void TypeInfo::SetProperty(BaseObject* object, const std::string& name, Property::Value value) const
+{
+ RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PropertyNameFinder<RegisteredPropertyPair>(ConstString(name)));
+ if ( iter != mRegisteredProperties.end() )
+ {
+ DALI_ASSERT_ALWAYS( iter->second.setFunc && "Trying to write to a read-only property" );
+
+ if( mCSharpType )
{
- GetImplementation(base).SetProperty( object, name, value );
+ // CSharp wants a property name not an index
+ iter->second.cSharpSetFunc( object,name.c_str(), const_cast< Property::Value* >(&value ));
}
else
{
- DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
+ iter->second.setFunc(object, iter->first, std::move(value));
}
}
+ else if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
+ {
+ // call base type recursively
+ mBaseType->SetProperty(object, name, std::move(value));
+ }
+ else
+ {
+ DALI_LOG_ERROR( "Property %s not found", name.c_str() );
+ }
}
Property::Value TypeInfo::GetProperty( const BaseObject *object, Property::Index index ) const
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
+ auto name = (iter->second).name;
+
+ return *(iter->second.cSharpGetFunc(const_cast<BaseObject*>(object), name.GetCString()));
+ }
+ 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 );
- if ( base )
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
{
- return GetImplementation( base ).GetProperty( object, index );
+ // call base type recursively
+ return mBaseType->GetProperty( object, index );
}
- DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
+ DALI_LOG_ERROR( "Property index %d not found\n", index );
+ return Property::Value();
}
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 ) );
+ RegisteredPropertyContainer::const_iterator iter = find_if(mRegisteredProperties.begin(), mRegisteredProperties.end(), PropertyNameFinder<RegisteredPropertyPair>(ConstString(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 );
- if ( base )
+ if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) )
{
- return GetImplementation( base ).GetProperty( object, name );
+ // call base type recursively
+ return mBaseType->GetProperty( object, name );
}
- DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
+ DALI_LOG_ERROR( "Property %s not found", name.c_str() );
+ return Property::Value();
}
} // namespace Internal