2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/common/type-info-impl.h>
22 #include <algorithm> // std::find_if
26 #include <dali/integration-api/debug.h>
27 #include <dali/internal/event/common/type-registry-impl.h>
28 #include <dali/internal/event/common/object-impl.h>
36 * Functor to find by given type for vector of pairs
38 template <typename S, typename T>
41 PairFinder(const S& find)
46 bool operator()(const T& p) const
48 return p.first == mFind;
57 * Functor to find a matching property name
60 struct PropertyNameFinder
62 PropertyNameFinder( const std::string& find )
67 bool operator()(const T &p) const
69 return p.second.name == mFind;
74 const std::string& mFind;
78 * Functor to find a matching property component index
81 struct PropertyComponentFinder
83 PropertyComponentFinder( Dali::Property::Index basePropertyIndex, const int find )
84 : mBasePropertyIndex( basePropertyIndex ),
89 bool operator()(const T &p) const
91 return ( p.second.basePropertyIndex == mBasePropertyIndex && p.second.componentIndex == mFind );
96 Dali::Property::Index mBasePropertyIndex;
108 TypeInfo::TypeInfo(const std::string &name, const std::string &baseTypeName, Dali::TypeInfo::CreateFunction creator)
109 : mTypeName(name), mBaseTypeName(baseTypeName), mCSharpType(false), mCreate(creator)
111 DALI_ASSERT_ALWAYS(!name.empty() && "Type info construction must have a name");
112 DALI_ASSERT_ALWAYS(!baseTypeName.empty() && "Type info construction must have a base type name");
115 TypeInfo::TypeInfo(const std::string &name, const std::string &baseTypeName, Dali::CSharpTypeInfo::CreateFunction creator)
116 : mTypeName(name), mBaseTypeName(baseTypeName), mCSharpType(true), mCSharpCreate(creator)
118 DALI_ASSERT_ALWAYS(!name.empty() && "Type info construction must have a name");
119 DALI_ASSERT_ALWAYS(!baseTypeName.empty() && "Type info construction must have a base type name");
122 TypeInfo::~TypeInfo()
126 BaseHandle TypeInfo::CreateInstance() const
134 ret = *mCSharpCreate();
143 BaseObject& handle = ret.GetBaseObject();
144 Object *object = dynamic_cast<Internal::Object*>(&handle);
148 object->SetTypeInfo( this );
155 bool TypeInfo::DoActionTo(BaseObject *object, const std::string &actionName, const Property::Map &properties)
159 ActionContainer::iterator iter = find_if(mActions.begin(), mActions.end(), PairFinder<std::string, ActionPair>(actionName));
161 if( iter != mActions.end() )
163 done = (iter->second)(object, actionName, properties);
167 DALI_LOG_WARNING("Type '%s' cannot do action '%s'\n", mTypeName.c_str(), actionName.c_str());
172 Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
175 done = GetImplementation(base).DoActionTo(object, actionName, properties);
180 base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
187 bool TypeInfo::ConnectSignal( BaseObject* object, ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functor )
189 bool connected( false );
191 ConnectorContainer::iterator iter = find_if( mSignalConnectors.begin(), mSignalConnectors.end(),
192 PairFinder<std::string, ConnectionPair>(signalName) );
194 if( iter != mSignalConnectors.end() )
196 connected = (iter->second)( object, connectionTracker, signalName, functor );
202 const std::string& TypeInfo::GetName() const
207 const std::string& TypeInfo::GetBaseName() const
209 return mBaseTypeName;
212 Dali::TypeInfo::CreateFunction TypeInfo::GetCreator() const
217 size_t TypeInfo::GetActionCount() const
219 size_t count = mActions.size();
221 Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
224 count += GetImplementation(base).mActions.size();
225 base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
231 std::string TypeInfo::GetActionName(size_t index) const
235 if( index < mActions.size() )
237 name = mActions[index].first;
241 size_t count = mActions.size();
243 Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
246 size_t baseCount = GetImplementation(base).mActions.size();
248 if( index < count + baseCount )
250 name = GetImplementation(base).mActions[ index - count ].first;
256 base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
263 size_t TypeInfo::GetSignalCount() const
265 size_t count = mSignalConnectors.size();
267 Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
270 count += GetImplementation(base).mSignalConnectors.size();
271 base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
277 std::string TypeInfo::GetSignalName(size_t index) const
281 if( index < mSignalConnectors.size() )
283 name = mSignalConnectors[index].first;
287 size_t count = mSignalConnectors.size();
289 Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
292 size_t baseCount = GetImplementation(base).mSignalConnectors.size();
294 if( index < count + baseCount )
296 name = GetImplementation(base).mSignalConnectors[ index - count ].first;
302 base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
309 void TypeInfo::GetPropertyIndices( Property::IndexContainer& indices ) const
311 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
314 const TypeInfo& baseImpl( GetImplementation( base ) );
315 baseImpl.GetPropertyIndices( indices );
318 if ( ! mRegisteredProperties.empty() )
320 indices.Reserve( indices.Size() + mRegisteredProperties.size() );
322 const RegisteredPropertyContainer::const_iterator endIter = mRegisteredProperties.end();
323 for ( RegisteredPropertyContainer::const_iterator iter = mRegisteredProperties.begin(); iter != endIter; ++iter )
325 indices.PushBack( iter->first );
330 const std::string& TypeInfo::GetPropertyName( Property::Index index ) const
332 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
333 PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
335 if ( iter != mRegisteredProperties.end() )
337 return iter->second.name;
340 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
343 return GetImplementation(base).GetPropertyName( index );
346 DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
349 void TypeInfo::AddActionFunction( const std::string &actionName, Dali::TypeInfo::ActionFunction function )
351 if( NULL == function)
353 DALI_LOG_WARNING("Action function is empty\n");
357 ActionContainer::iterator iter = std::find_if(mActions.begin(), mActions.end(),
358 PairFinder<std::string, ActionPair>(actionName));
360 if( iter == mActions.end() )
362 mActions.push_back( ActionPair( actionName, function ) );
366 DALI_LOG_WARNING("Action already exists in TypeRegistry Type\n", actionName.c_str());
371 void TypeInfo::AddConnectorFunction( const std::string& signalName, Dali::TypeInfo::SignalConnectorFunction function )
373 if( NULL == function)
375 DALI_LOG_WARNING("Connector function is empty\n");
379 ConnectorContainer::iterator iter = find_if( mSignalConnectors.begin(), mSignalConnectors.end(),
380 PairFinder<std::string, ConnectionPair>(signalName) );
382 if( iter == mSignalConnectors.end() )
384 mSignalConnectors.push_back( ConnectionPair( signalName, function ) );
388 DALI_LOG_WARNING("Signal name already exists in TypeRegistry Type for signal connector function\n", signalName.c_str());
393 void TypeInfo::AddProperty( const std::string& name, Property::Index index, Property::Type type, Dali::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc )
395 // The setter can be empty as a property can be read-only.
397 if ( NULL == getFunc )
399 DALI_ASSERT_ALWAYS( ! "GetProperty Function is empty" );
403 RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
404 PairFinder< Property::Index, RegisteredPropertyPair>(index) );
406 if ( iter == mRegisteredProperties.end() )
408 mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, setFunc, getFunc, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
412 DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
417 void TypeInfo::AddProperty( const std::string& name, Property::Index index, Property::Type type, Dali::CSharpTypeInfo::SetPropertyFunction setFunc, Dali::CSharpTypeInfo::GetPropertyFunction getFunc)
420 // The setter can be empty as a property can be read-only.
422 if ( NULL == getFunc )
424 DALI_ASSERT_ALWAYS( ! "GetProperty Function is empty" );
428 RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
429 PairFinder< Property::Index, RegisteredPropertyPair>(index) );
431 if ( iter == mRegisteredProperties.end() )
433 mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, setFunc, getFunc, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
437 DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
444 void TypeInfo::AddAnimatableProperty( const std::string& name, Property::Index index, Property::Type type )
446 RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
447 PairFinder< Property::Index, RegisteredPropertyPair>(index) );
449 if ( iter == mRegisteredProperties.end() )
451 mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
455 DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
459 void TypeInfo::AddAnimatableProperty( const std::string& name, Property::Index index, const Property::Value& defaultValue )
461 RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
462 PairFinder< Property::Index, RegisteredPropertyPair>(index) );
464 if ( iter == mRegisteredProperties.end() )
466 mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( defaultValue.GetType(), name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
467 mPropertyDefaultValues.push_back( PropertyDefaultValuePair( index, defaultValue ) );
471 DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
475 void TypeInfo::AddAnimatablePropertyComponent( const std::string& name, Property::Index index, Property::Index baseIndex, unsigned int componentIndex )
477 Property::Type type = GetPropertyType( baseIndex );
478 DALI_ASSERT_ALWAYS( ( type == Property::VECTOR2 || type == Property::VECTOR3 || type == Property::VECTOR4 ) && "Base property does not support component" );
480 bool success = false;
482 RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
483 PairFinder< Property::Index, RegisteredPropertyPair>(index) );
485 if ( iter == mRegisteredProperties.end() )
487 iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
488 PropertyComponentFinder< RegisteredPropertyPair >( baseIndex, componentIndex ) );
490 if ( iter == mRegisteredProperties.end() )
492 mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, name, baseIndex, componentIndex ) ) );
497 DALI_ASSERT_ALWAYS( success && "Property component already registered" );
500 void TypeInfo::AddChildProperty( const std::string& name, Property::Index index, Property::Type type )
502 RegisteredPropertyContainer::iterator iter = find_if( mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(),
503 PairFinder< Property::Index, RegisteredPropertyPair>(index) );
505 if ( iter == mRegisteredChildProperties.end() )
507 mRegisteredChildProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
511 DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
515 size_t TypeInfo::GetPropertyCount() const
517 size_t count( mRegisteredProperties.size() );
519 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
522 const TypeInfo& baseImpl( GetImplementation(base) );
523 count += baseImpl.mRegisteredProperties.size();
524 base = TypeRegistry::Get()->GetTypeInfo( baseImpl.mBaseTypeName );
530 Property::Index TypeInfo::GetPropertyIndex( const std::string& name ) const
532 Property::Index index = Property::INVALID_INDEX;
534 // Slow but should not be done that often
535 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
536 PropertyNameFinder< RegisteredPropertyPair >( name ) );
538 if ( iter != mRegisteredProperties.end() )
544 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
547 index = GetImplementation(base).GetPropertyIndex( name );
554 Property::Index TypeInfo::GetBasePropertyIndex( Property::Index index ) const
556 Property::Index basePropertyIndex = Property::INVALID_INDEX;
558 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
559 PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
561 if ( iter != mRegisteredProperties.end() )
563 basePropertyIndex = iter->second.basePropertyIndex;
567 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
570 basePropertyIndex = GetImplementation(base).GetBasePropertyIndex( index );
574 return basePropertyIndex;
577 int TypeInfo::GetComponentIndex( Property::Index index ) const
579 int componentIndex = Property::INVALID_COMPONENT_INDEX;
581 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
582 PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
584 if ( iter != mRegisteredProperties.end() )
586 componentIndex = iter->second.componentIndex;
590 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
593 componentIndex = GetImplementation(base).GetComponentIndex( index );
597 return componentIndex;
600 Property::Index TypeInfo::GetChildPropertyIndex( const std::string& name ) const
602 Property::Index index = Property::INVALID_INDEX;
604 // Slow but should not be done that often
605 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(),
606 PropertyNameFinder< RegisteredPropertyPair >( name ) );
608 if ( iter != mRegisteredChildProperties.end() )
614 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
617 index = GetImplementation(base).GetChildPropertyIndex( name );
624 const std::string& TypeInfo::GetChildPropertyName( Property::Index index ) const
626 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(),
627 PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
629 if ( iter != mRegisteredChildProperties.end() )
631 return iter->second.name;
634 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
637 return GetImplementation(base).GetChildPropertyName( index );
640 DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
643 Property::Type TypeInfo::GetChildPropertyType( Property::Index index ) const
645 Property::Type type( Property::NONE );
647 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(),
648 PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
650 if ( iter != mRegisteredChildProperties.end() )
652 type = iter->second.type;
656 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
659 type = GetImplementation(base).GetChildPropertyType( index );
663 DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
670 bool TypeInfo::IsPropertyWritable( Property::Index index ) const
672 bool writable( false );
674 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
675 PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
677 if ( iter != mRegisteredProperties.end() )
679 if( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
681 writable = true; // animatable property is writable
685 writable = iter->second.setFunc ? true : false;
690 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
693 writable = GetImplementation(base).IsPropertyWritable( index );
697 DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
704 Property::Type TypeInfo::GetPropertyType( Property::Index index ) const
706 Property::Type type( Property::NONE );
708 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
709 PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
711 if ( iter != mRegisteredProperties.end() )
713 type = iter->second.type;
717 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
720 type = GetImplementation(base).GetPropertyType( index );
724 DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
731 Property::Value TypeInfo::GetPropertyDefaultValue( Property::Index index ) const
733 PropertyDefaultValueContainer::const_iterator iter = find_if( mPropertyDefaultValues.begin(), mPropertyDefaultValues.end(),
734 PairFinder< Property::Index, PropertyDefaultValuePair >( index ) );
735 if( iter != mPropertyDefaultValues.end() )
741 return Property::Value( GetPropertyType( index ) );
745 void TypeInfo::SetProperty( BaseObject *object, Property::Index index, const Property::Value& value ) const
747 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
748 PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
749 if ( iter != mRegisteredProperties.end() )
751 if( iter->second.setFunc )
753 iter->second.setFunc( object, index, value );
758 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
761 GetImplementation(base).SetProperty( object, index, value );
765 DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
770 void TypeInfo::SetProperty( BaseObject *object, const std::string& name, const Property::Value& value ) const
772 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
773 PropertyNameFinder< RegisteredPropertyPair >( name ) );
774 if ( iter != mRegisteredProperties.end() )
776 DALI_ASSERT_ALWAYS( iter->second.setFunc && "Trying to write to a read-only property" );
777 iter->second.setFunc( object, iter->first, value );
781 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
784 GetImplementation(base).SetProperty( object, name, value );
788 DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
793 Property::Value TypeInfo::GetProperty( const BaseObject *object, Property::Index index ) const
795 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
796 PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
797 if( iter != mRegisteredProperties.end() )
799 if( mCSharpType ) // using csharp property get which returns a pointer to a Property::Value
801 // CSharp can't return any object by value, it can return pointers.
802 // CSharp has ownership of the pointer contents, which is fine because we are returning by value
803 int index = (iter->first );
804 return *( iter->second.cSharpGetFunc( const_cast< BaseObject* >( object ), &index ));
809 // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
810 return iter->second.getFunc( const_cast< BaseObject* >( object ), index );
814 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
817 return GetImplementation( base ).GetProperty( object, index );
820 DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
823 Property::Value TypeInfo::GetProperty( const BaseObject *object, const std::string& name ) const
825 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
826 PropertyNameFinder< RegisteredPropertyPair >( name ) );
827 if( iter != mRegisteredProperties.end() )
829 if( mCSharpType ) // using csharp property get which returns a pointer to a Property::Value
831 // CSharp can't return any object by value, it can return pointers.
832 // CSharp has ownership of the pointer contents, which is fine because we are returning by value
833 int index = (iter->first );
834 return *( iter->second.cSharpGetFunc( const_cast< BaseObject* >( object ), &index ));
839 // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
840 return iter->second.getFunc( const_cast< BaseObject* >( object ), iter->first );
844 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
847 return GetImplementation( base ).GetProperty( object, name );
850 DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
853 } // namespace Internal