X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Fcommon%2Ftype-info-impl.cpp;h=65f63fc36929069b3141cff2cb32217775c27b40;hb=aee2350a06fac17860817a0e84ff97a4553dbbaa;hp=a4cf3bb82860f5586cb2d2affb4efbb4665a5a43;hpb=166eeb41088968e832177eba04b18d8e6c2299fd;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/event/common/type-info-impl.cpp b/dali/internal/event/common/type-info-impl.cpp index a4cf3bb..65f63fc 100644 --- a/dali/internal/event/common/type-info-impl.cpp +++ b/dali/internal/event/common/type-info-impl.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -25,10 +25,16 @@ // INTERNAL INCLUDES #include #include -#include +#include using std::find_if; +namespace Dali +{ + +namespace Internal +{ + namespace { @@ -74,16 +80,97 @@ private: const std::string& mFind; }; -} // namespace anon +/** + * Functor to find a matching property component index + */ +template +struct PropertyComponentFinder +{ + PropertyComponentFinder( Property::Index basePropertyIndex, const int find ) + : mBasePropertyIndex( basePropertyIndex ), + mFind( find ) + { + } + + bool operator()(const T &p) const + { + return ( p.second.basePropertyIndex == mBasePropertyIndex && p.second.componentIndex == mFind ); + } -namespace Dali +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( 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(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"); @@ -99,23 +186,32 @@ BaseHandle TypeInfo::CreateInstance() const 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 ) { BaseObject& handle = ret.GetBaseObject(); - ProxyObject *proxyObject = dynamic_cast(&handle); + Object *object = dynamic_cast(&handle); - if ( proxyObject ) + if ( object ) { - proxyObject->SetTypeInfo( this ); + object->SetTypeInfo( this ); } } } return ret; } -bool TypeInfo::DoActionTo(BaseObject *object, const std::string &actionName, const std::vector &properties) +bool TypeInfo::DoActionTo(BaseObject *object, const std::string &actionName, const Property::Map &properties) { bool done = false; @@ -125,22 +221,13 @@ bool TypeInfo::DoActionTo(BaseObject *object, const std::string &actionName, con { 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 ); } } @@ -159,6 +246,15 @@ bool TypeInfo::ConnectSignal( BaseObject* object, ConnectionTrackerInterface* co 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; } @@ -177,106 +273,172 @@ Dali::TypeInfo::CreateFunction TypeInfo::GetCreator() const return mCreate; } -void TypeInfo::GetActions( Dali::TypeInfo::NameContainer& ret ) const +size_t TypeInfo::GetActionCount() const { - for(ActionContainer::const_iterator iter = mActions.begin(); iter != mActions.end(); ++iter) - { - ret.push_back(iter->first); - } + size_t count = 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(size_t index) const { - for(ConnectorContainer::const_iterator iter = mSignalConnectors.begin(); iter != mSignalConnectors.end(); ++iter) + std::string name; + const size_t count = 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 +size_t TypeInfo::GetSignalCount() const { - Property::IndexContainer indices; + size_t count = 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(size_t index) const +{ + std::string name; + const size_t count = 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 +const std::string& 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; } + 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 TypeInfo::GetPropertyName( Property::Index index ) const +{ + std::string propertyName; + // default or custom + if ( mDefaultProperties && ( index < DEFAULT_PROPERTY_MAX_COUNT ) ) { - return GetImplementation(base).GetPropertyName( index ); + const char* name = nullptr; + 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; + } + } + // 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 ProxyObject + return propertyName; } void TypeInfo::AddActionFunction( const std::string &actionName, Dali::TypeInfo::ActionFunction function ) @@ -296,7 +458,7 @@ void TypeInfo::AddActionFunction( const std::string &actionName, Dali::TypeInfo: } 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()); } } } @@ -318,7 +480,7 @@ void TypeInfo::AddConnectorFunction( const std::string& signalName, Dali::TypeIn } 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()); } } } @@ -338,25 +500,121 @@ void TypeInfo::AddProperty( const std::string& name, Property::Index index, Prop if ( iter == mRegisteredProperties.end() ) { - mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, setFunc, getFunc, name ) ) ); + 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" ); } -unsigned int TypeInfo::GetPropertyCount() const +void TypeInfo::AddChildProperty( const std::string& name, Property::Index index, Property::Type type ) { - unsigned int count( mRegisteredProperties.size() ); + RegisteredPropertyContainer::iterator iter = find_if( mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(), + PairFinder< Property::Index, RegisteredPropertyPair>(index) ); - Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName ); - while ( base ) + if ( iter == mRegisteredChildProperties.end() ) + { + mRegisteredChildProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) ); + } + else { - const TypeInfo& baseImpl( GetImplementation(base) ); - count += baseImpl.mRegisteredProperties.size(); - base = TypeRegistry::Get()->GetTypeInfo( baseImpl.mBaseTypeName ); + DALI_ASSERT_ALWAYS( ! "Property index already added to Type" ); + } +} + +uint32_t TypeInfo::GetPropertyCount() const +{ + uint32_t count = mDefaultPropertyCount + static_cast( mRegisteredProperties.size() ); + + if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) ) + { + // call base type recursively + count += mBaseType->GetPropertyCount(); } return count; @@ -365,81 +623,330 @@ unsigned int TypeInfo::GetPropertyCount() const Property::Index TypeInfo::GetPropertyIndex( const std::string& name ) const { Property::Index index = Property::INVALID_INDEX; + bool found = false; - // 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() ) + // check default properties + if( mDefaultProperties ) { - index = iter->first; + for( Property::Index tableIndex = 0; tableIndex < mDefaultPropertyCount; ++tableIndex ) + { + if( 0 == name.compare( mDefaultProperties[ tableIndex ].name ) ) + { + index = mDefaultProperties[ tableIndex ].enumIndex; + found = true; + break; + } + } } - else + if( !found ) { - Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName ); - if ( base ) + // 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 ) ) { - index = GetImplementation(base).GetPropertyIndex( name ); + // 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; +} + +int 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( 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 { - 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() ) { - writable = GetImplementation(base).IsPropertyWritable( index ); + 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_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as ProxyObject + 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 ); + } + else + { + DALI_LOG_ERROR( "Property index %d not found\n", index ); + } + } + + return animatable; +} + +bool TypeInfo::IsPropertyAConstraintInput( Property::Index index ) const +{ + bool constraintInput = false; + bool found = false; + + // default property? + if ( ( index < DEFAULT_PROPERTY_MAX_COUNT ) && mDefaultProperties ) + { + 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 ) ) + { + // 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; - 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::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() ) + { + 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 ) ) { - type = GetImplementation(base).GetPropertyType( index ); + // call base type recursively + type = mBaseType->GetPropertyType( index ); } else { - DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as ProxyObject + DALI_LOG_ERROR( "Property index %d not found\n", index ); } } 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(), @@ -448,20 +955,27 @@ void TypeInfo::SetProperty( BaseObject *object, Property::Index index, const Pro { 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( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) ) + { + // call base type recursively + mBaseType->SetProperty( object, index, value ); + } else { - Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName ); - if ( base ) - { - GetImplementation(base).SetProperty( object, index, value ); - } - else - { - DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as ProxyObject - } + DALI_LOG_ERROR( "Property index %d not found\n", index ); } } @@ -472,20 +986,26 @@ void TypeInfo::SetProperty( BaseObject *object, const std::string& name, const P 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 ); - } - else - { - Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName ); - if ( base ) + + 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, value ); } } + else if( GetBaseType( mBaseType, mTypeRegistry, mBaseTypeName ) ) + { + // call base type recursively + mBaseType->SetProperty( object, name, value ); + } + else + { + DALI_LOG_ERROR( "Property %s not found", name.c_str() ); + } } Property::Value TypeInfo::GetProperty( const BaseObject *object, Property::Index index ) const @@ -494,36 +1014,65 @@ Property::Value TypeInfo::GetProperty( const BaseObject *object, Property::Index 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 ); - 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 ProxyObject + 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 ) ); + 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 ); - 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