2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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.
18 #include <dali/internal/event/common/type-info-impl.h>
21 #include <algorithm> // std::find_if
25 #include <dali/integration-api/debug.h>
26 #include <dali/internal/event/common/type-registry-impl.h>
27 #include <dali/internal/event/common/proxy-object.h>
35 * Functor to find by given type for vector of pairs
37 template <typename S, typename T>
40 PairFinder(const S& find)
45 bool operator()(const T& p) const
47 return p.first == mFind;
56 * Functor to find a matching property name
59 struct PropertyNameFinder
61 PropertyNameFinder( const std::string& find )
66 bool operator()(const T &p) const
68 return p.second.name == mFind;
73 const std::string& mFind;
84 TypeInfo::TypeInfo(const std::string &name, const std::string &baseTypeName, Dali::TypeInfo::CreateFunction creator)
85 : mTypeName(name), mBaseTypeName(baseTypeName), mCreate(creator)
87 DALI_ASSERT_ALWAYS(!name.empty() && "Type info construction must have a name");
88 DALI_ASSERT_ALWAYS(!baseTypeName.empty() && "Type info construction must have a base type name");
95 BaseHandle TypeInfo::CreateInstance()
105 BaseObject& handle = ret.GetBaseObject();
106 ProxyObject *proxyObject = dynamic_cast<Internal::ProxyObject*>(&handle);
110 proxyObject->SetTypeInfo( this );
117 bool TypeInfo::DoActionTo(BaseObject *object, const std::string &actionName, const std::vector<Property::Value> &properties)
121 ActionContainer::iterator iter = find_if(mActions.begin(), mActions.end(), PairFinder<std::string, ActionPair>(actionName));
123 if( iter != mActions.end() )
125 done = (iter->second)(object, actionName, properties);
129 DALI_LOG_WARNING("Type '%s' cannot do action '%s'\n", mTypeName.c_str(), actionName.c_str());
134 Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
137 done = GetImplementation(base).DoActionTo(object, actionName, properties);
142 base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
149 bool TypeInfo::ConnectSignal( BaseObject* object, ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functor )
151 bool connected( false );
153 ConnectorContainerV2::iterator iter = find_if( mSignalConnectors.begin(), mSignalConnectors.end(),
154 PairFinder<std::string, ConnectionPairV2>(signalName) );
156 if( iter != mSignalConnectors.end() )
158 connected = (iter->second)( object, connectionTracker, signalName, functor );
164 const std::string& TypeInfo::GetName()
169 const std::string& TypeInfo::GetBaseName()
171 return mBaseTypeName;
174 Dali::TypeInfo::CreateFunction TypeInfo::GetCreator()
179 Dali::TypeInfo::NameContainer TypeInfo::GetActions()
181 Dali::TypeInfo::NameContainer ret;
183 for(ActionContainer::iterator iter = mActions.begin(); iter != mActions.end(); ++iter)
185 ret.push_back(iter->first);
188 Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
191 for(ActionContainer::iterator iter = GetImplementation(base).mActions.begin();
192 iter != GetImplementation(base).mActions.end(); ++iter)
194 ret.push_back(iter->first);
197 base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
203 Dali::TypeInfo::NameContainer TypeInfo::GetSignals()
205 Dali::TypeInfo::NameContainer ret;
207 for(ConnectorContainerV2::iterator iter = mSignalConnectors.begin(); iter != mSignalConnectors.end(); ++iter)
209 ret.push_back(iter->first);
212 Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
215 for(ConnectorContainerV2::iterator iter = GetImplementation(base).mSignalConnectors.begin();
216 iter != GetImplementation(base).mSignalConnectors.end(); ++iter)
218 ret.push_back(iter->first);
221 base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
227 void TypeInfo::GetPropertyIndices( Property::IndexContainer& indices ) const
229 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
232 const TypeInfo& baseImpl( GetImplementation( base ) );
233 baseImpl.GetPropertyIndices( indices );
236 if ( ! mRegisteredProperties.empty() )
238 indices.reserve( indices.size() + mRegisteredProperties.size() );
240 const RegisteredPropertyContainer::const_iterator endIter = mRegisteredProperties.end();
241 for ( RegisteredPropertyContainer::const_iterator iter = mRegisteredProperties.begin(); iter != endIter; ++iter )
243 indices.push_back( iter->first );
248 const std::string& TypeInfo::GetPropertyName( Property::Index index ) const
250 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
251 PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
253 if ( iter != mRegisteredProperties.end() )
255 return iter->second.name;
258 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
261 return GetImplementation(base).GetPropertyName( index );
264 DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as ProxyObject
266 // Property not found, return reference to invalid property string.
267 static const std::string EMPTY_PROPERTY_NAME;
268 return EMPTY_PROPERTY_NAME;
271 void TypeInfo::AddActionFunction( const std::string &actionName, Dali::TypeInfo::ActionFunction function )
273 if( NULL == function)
275 DALI_LOG_WARNING("Action function is empty\n");
279 ActionContainer::iterator iter = std::find_if(mActions.begin(), mActions.end(),
280 PairFinder<std::string, ActionPair>(actionName));
282 if( iter == mActions.end() )
284 mActions.push_back( ActionPair( actionName, function ) );
288 DALI_LOG_WARNING("Action already exists in TypeRegistry Type", actionName.c_str());
293 void TypeInfo::AddConnectorFunction( const std::string& signalName, Dali::TypeInfo::SignalConnectorFunctionV2 function )
295 if( NULL == function)
297 DALI_LOG_WARNING("Connector function is empty\n");
301 ConnectorContainerV2::iterator iter = find_if( mSignalConnectors.begin(), mSignalConnectors.end(),
302 PairFinder<std::string, ConnectionPairV2>(signalName) );
304 if( iter == mSignalConnectors.end() )
306 mSignalConnectors.push_back( ConnectionPairV2( signalName, function ) );
310 DALI_LOG_WARNING("Signal name already exists in TypeRegistry Type for signal connector function", signalName.c_str());
315 void TypeInfo::AddProperty( const std::string& name, Property::Index index, Property::Type type, Dali::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc )
317 // The setter can be empty as a property can be read-only.
319 if ( NULL == getFunc )
321 DALI_ASSERT_ALWAYS( ! "GetProperty Function is empty" );
325 RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
326 PairFinder< Property::Index, RegisteredPropertyPair>(index) );
328 if ( iter == mRegisteredProperties.end() )
330 mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, setFunc, getFunc, name ) ) );
334 DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
339 unsigned int TypeInfo::GetPropertyCount() const
341 unsigned int count( mRegisteredProperties.size() );
343 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
346 const TypeInfo& baseImpl( GetImplementation(base) );
347 count += baseImpl.mRegisteredProperties.size();
348 base = TypeRegistry::Get()->GetTypeInfo( baseImpl.mBaseTypeName );
354 Property::Index TypeInfo::GetPropertyIndex( const std::string& name ) const
356 Property::Index index = Property::INVALID_INDEX;
358 // Slow but should not be done that often
359 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
360 PropertyNameFinder< RegisteredPropertyPair >( name ) );
362 if ( iter != mRegisteredProperties.end() )
368 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
371 index = GetImplementation(base).GetPropertyIndex( name );
378 bool TypeInfo::IsPropertyWritable( Property::Index index ) const
380 bool writable( false );
382 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
383 PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
385 if ( iter != mRegisteredProperties.end() )
387 writable = iter->second.setFunc ? true : false;
391 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
394 writable = GetImplementation(base).IsPropertyWritable( index );
398 DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as ProxyObject
405 Property::Type TypeInfo::GetPropertyType( Property::Index index ) const
407 Property::Type type( Property::NONE );
409 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
410 PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
412 if ( iter != mRegisteredProperties.end() )
414 type = iter->second.type;
418 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
421 type = GetImplementation(base).GetPropertyType( index );
425 DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as ProxyObject
432 void TypeInfo::SetProperty( BaseObject *object, Property::Index index, const Property::Value& value )
434 RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
435 PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
436 if ( iter != mRegisteredProperties.end() )
438 DALI_ASSERT_ALWAYS( iter->second.setFunc && "Trying to write to a read-only property" );
439 iter->second.setFunc( object, index, value );
443 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
446 GetImplementation(base).SetProperty( object, index, value );
450 DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as ProxyObject
455 void TypeInfo::SetProperty( BaseObject *object, const std::string& name, const Property::Value& value )
457 RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
458 PropertyNameFinder< RegisteredPropertyPair >( name ) );
459 if ( iter != mRegisteredProperties.end() )
461 DALI_ASSERT_ALWAYS( iter->second.setFunc && "Trying to write to a read-only property" );
462 iter->second.setFunc( object, iter->first, value );
466 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
469 GetImplementation(base).SetProperty( object, name, value );
473 DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
478 Property::Value TypeInfo::GetProperty( const BaseObject *object, Property::Index index )
480 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
481 PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
482 if( iter != mRegisteredProperties.end() )
484 // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
485 return iter->second.getFunc( const_cast< BaseObject* >( object ), index );
488 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
491 return GetImplementation( base ).GetProperty( object, index );
494 DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as ProxyObject
496 return Property::Value();
499 Property::Value TypeInfo::GetProperty( const BaseObject *object, const std::string& name )
501 RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
502 PropertyNameFinder< RegisteredPropertyPair >( name ) );
503 if( iter != mRegisteredProperties.end() )
505 // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
506 return iter->second.getFunc( const_cast< BaseObject* >( object ), iter->first );
509 Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
512 return GetImplementation( base ).GetProperty( object, name );
515 DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
517 return Property::Value();
520 } // namespace Internal