Revert "License conversion from Flora to Apache 2.0"
[platform/core/uifw/dali-core.git] / dali / internal / event / common / type-info-impl.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
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
7 //
8 //     http://floralicense.org/license/
9 //
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.
15 //
16
17 // CLASS HEADER
18 #include <dali/internal/event/common/type-info-impl.h>
19
20 // EXTERNAL INCLUDES
21 #include <algorithm> // std::find_if
22 #include <string>
23
24 // INTERNAL INCLUDES
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>
28
29 using std::find_if;
30
31 namespace
32 {
33
34 /*
35  * Functor to find by given type for vector of pairs
36  */
37 template <typename S, typename T>
38 struct PairFinder
39 {
40   PairFinder(const S& find)
41   : mFind(find)
42   {
43   }
44
45   bool operator()(const T& p) const
46   {
47     return p.first == mFind;
48   }
49
50 private:
51
52   const S& mFind;
53 };
54
55 /**
56  * Functor to find a matching property name
57  */
58 template <typename T>
59 struct PropertyNameFinder
60 {
61   PropertyNameFinder( const std::string& find )
62   : mFind( find )
63   {
64   }
65
66   bool operator()(const T &p) const
67   {
68     return p.second.name == mFind;
69   }
70
71 private:
72
73   const std::string& mFind;
74 };
75
76 } // namespace anon
77
78 namespace Dali
79 {
80
81 namespace Internal
82 {
83
84 TypeInfo::TypeInfo(const std::string &name, const std::string &baseTypeName, Dali::TypeInfo::CreateFunction creator)
85   : mTypeName(name), mBaseTypeName(baseTypeName), mCreate(creator)
86 {
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");
89 }
90
91 TypeInfo::~TypeInfo()
92 {
93 }
94
95 BaseHandle TypeInfo::CreateInstance()
96 {
97   BaseHandle ret;
98
99   if(mCreate)
100   {
101     ret = mCreate();
102
103     if ( ret )
104     {
105       BaseObject& handle = ret.GetBaseObject();
106       ProxyObject *proxyObject = dynamic_cast<Internal::ProxyObject*>(&handle);
107
108       if ( proxyObject )
109       {
110         proxyObject->SetTypeInfo( this );
111       }
112     }
113   }
114   return ret;
115 }
116
117 bool TypeInfo::DoActionTo(BaseObject *object, const std::string &actionName, const std::vector<Property::Value> &properties)
118 {
119   bool done = false;
120
121   ActionContainer::iterator iter = find_if(mActions.begin(), mActions.end(), PairFinder<std::string, ActionPair>(actionName));
122
123   if( iter != mActions.end() )
124   {
125     done = (iter->second)(object, actionName, properties);
126   }
127   else
128   {
129     DALI_LOG_WARNING("Type '%s' cannot do action '%s'\n", mTypeName.c_str(), actionName.c_str());
130   }
131
132   if(!done)
133   {
134     Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
135     while( base )
136     {
137       done = GetImplementation(base).DoActionTo(object, actionName, properties);
138       if( done )
139       {
140         break;
141       }
142       base =  Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
143     }
144   }
145
146   return done;
147 }
148
149 bool TypeInfo::ConnectSignal( BaseObject* object, ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functor )
150 {
151   bool connected( false );
152
153   ConnectorContainerV2::iterator iter = find_if( mSignalConnectors.begin(), mSignalConnectors.end(),
154                                                  PairFinder<std::string, ConnectionPairV2>(signalName) );
155
156   if( iter != mSignalConnectors.end() )
157   {
158     connected = (iter->second)( object, connectionTracker, signalName, functor );
159   }
160
161   return connected;
162 }
163
164 const std::string& TypeInfo::GetName()
165 {
166   return mTypeName;
167 }
168
169 const std::string& TypeInfo::GetBaseName()
170 {
171   return mBaseTypeName;
172 }
173
174 Dali::TypeInfo::CreateFunction TypeInfo::GetCreator()
175 {
176   return mCreate;
177 }
178
179 Dali::TypeInfo::NameContainer TypeInfo::GetActions()
180 {
181   Dali::TypeInfo::NameContainer ret;
182
183   for(ActionContainer::iterator iter = mActions.begin(); iter != mActions.end(); ++iter)
184   {
185     ret.push_back(iter->first);
186   }
187
188   Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
189   while( base )
190   {
191     for(ActionContainer::iterator iter = GetImplementation(base).mActions.begin();
192         iter != GetImplementation(base).mActions.end(); ++iter)
193     {
194       ret.push_back(iter->first);
195     }
196
197     base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
198   }
199
200   return ret;
201 }
202
203 Dali::TypeInfo::NameContainer TypeInfo::GetSignals()
204 {
205   Dali::TypeInfo::NameContainer ret;
206
207   for(ConnectorContainerV2::iterator iter = mSignalConnectors.begin(); iter != mSignalConnectors.end(); ++iter)
208   {
209     ret.push_back(iter->first);
210   }
211
212   Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
213   while( base )
214   {
215     for(ConnectorContainerV2::iterator iter = GetImplementation(base).mSignalConnectors.begin();
216         iter != GetImplementation(base).mSignalConnectors.end(); ++iter)
217     {
218       ret.push_back(iter->first);
219     }
220
221     base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
222   }
223
224   return ret;
225 }
226
227 void TypeInfo::GetPropertyIndices( Property::IndexContainer& indices ) const
228 {
229   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
230   if ( base )
231   {
232     const TypeInfo& baseImpl( GetImplementation( base ) );
233     baseImpl.GetPropertyIndices( indices );
234   }
235
236   if ( ! mRegisteredProperties.empty() )
237   {
238     indices.reserve( indices.size() + mRegisteredProperties.size() );
239
240     const RegisteredPropertyContainer::const_iterator endIter = mRegisteredProperties.end();
241     for ( RegisteredPropertyContainer::const_iterator iter = mRegisteredProperties.begin(); iter != endIter; ++iter )
242     {
243       indices.push_back( iter->first );
244     }
245   }
246 }
247
248 const std::string& TypeInfo::GetPropertyName( Property::Index index ) const
249 {
250   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
251                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
252
253   if ( iter != mRegisteredProperties.end() )
254   {
255     return iter->second.name;
256   }
257
258   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
259   if ( base )
260   {
261     return GetImplementation(base).GetPropertyName( index );
262   }
263
264   DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as ProxyObject
265
266   // Property not found, return reference to invalid property string.
267   static const std::string EMPTY_PROPERTY_NAME;
268   return EMPTY_PROPERTY_NAME;
269 }
270
271 void TypeInfo::AddActionFunction( const std::string &actionName, Dali::TypeInfo::ActionFunction function )
272 {
273   if( NULL == function)
274   {
275     DALI_LOG_WARNING("Action function is empty\n");
276   }
277   else
278   {
279     ActionContainer::iterator iter = std::find_if(mActions.begin(), mActions.end(),
280                                                   PairFinder<std::string, ActionPair>(actionName));
281
282     if( iter == mActions.end() )
283     {
284       mActions.push_back( ActionPair( actionName, function ) );
285     }
286     else
287     {
288       DALI_LOG_WARNING("Action already exists in TypeRegistry Type", actionName.c_str());
289     }
290   }
291 }
292
293 void TypeInfo::AddConnectorFunction( const std::string& signalName, Dali::TypeInfo::SignalConnectorFunctionV2 function )
294 {
295   if( NULL == function)
296   {
297     DALI_LOG_WARNING("Connector function is empty\n");
298   }
299   else
300   {
301     ConnectorContainerV2::iterator iter = find_if( mSignalConnectors.begin(), mSignalConnectors.end(),
302                                                    PairFinder<std::string, ConnectionPairV2>(signalName) );
303
304     if( iter == mSignalConnectors.end() )
305     {
306       mSignalConnectors.push_back( ConnectionPairV2( signalName, function ) );
307     }
308     else
309     {
310       DALI_LOG_WARNING("Signal name already exists in TypeRegistry Type for signal connector function", signalName.c_str());
311     }
312   }
313 }
314
315 void TypeInfo::AddProperty( const std::string& name, Property::Index index, Property::Type type, Dali::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc )
316 {
317   // The setter can be empty as a property can be read-only.
318
319   if ( NULL == getFunc )
320   {
321     DALI_ASSERT_ALWAYS( ! "GetProperty Function is empty" );
322   }
323   else
324   {
325     RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
326                                                           PairFinder< Property::Index, RegisteredPropertyPair>(index) );
327
328     if ( iter == mRegisteredProperties.end() )
329     {
330       mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, setFunc, getFunc, name ) ) );
331     }
332     else
333     {
334       DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
335     }
336   }
337 }
338
339 unsigned int TypeInfo::GetPropertyCount() const
340 {
341   unsigned int count( mRegisteredProperties.size() );
342
343   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
344   while ( base )
345   {
346     const TypeInfo& baseImpl( GetImplementation(base) );
347     count += baseImpl.mRegisteredProperties.size();
348     base = TypeRegistry::Get()->GetTypeInfo( baseImpl.mBaseTypeName );
349   }
350
351   return count;
352 }
353
354 Property::Index TypeInfo::GetPropertyIndex( const std::string& name ) const
355 {
356   Property::Index index = Property::INVALID_INDEX;
357
358   // Slow but should not be done that often
359   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
360                                                           PropertyNameFinder< RegisteredPropertyPair >( name ) );
361
362   if ( iter != mRegisteredProperties.end() )
363   {
364     index = iter->first;
365   }
366   else
367   {
368     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
369     if ( base )
370     {
371       index = GetImplementation(base).GetPropertyIndex( name );
372     }
373   }
374
375   return index;
376 }
377
378 bool TypeInfo::IsPropertyWritable( Property::Index index ) const
379 {
380   bool writable( false );
381
382   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
383                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
384
385   if ( iter != mRegisteredProperties.end() )
386   {
387     writable = iter->second.setFunc ? true : false;
388   }
389   else
390   {
391     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
392     if ( base )
393     {
394       writable = GetImplementation(base).IsPropertyWritable( index );
395     }
396     else
397     {
398       DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as ProxyObject
399     }
400   }
401
402   return writable;
403 }
404
405 Property::Type TypeInfo::GetPropertyType( Property::Index index ) const
406 {
407   Property::Type type( Property::NONE );
408
409   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
410                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
411
412   if ( iter != mRegisteredProperties.end() )
413   {
414     type = iter->second.type;
415   }
416   else
417   {
418     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
419     if ( base )
420     {
421       type = GetImplementation(base).GetPropertyType( index );
422     }
423     else
424     {
425       DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as ProxyObject
426     }
427   }
428
429   return type;
430 }
431
432 void TypeInfo::SetProperty( BaseObject *object, Property::Index index, const Property::Value& value )
433 {
434   RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
435                                                     PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
436   if ( iter != mRegisteredProperties.end() )
437   {
438     DALI_ASSERT_ALWAYS( iter->second.setFunc && "Trying to write to a read-only property" );
439     iter->second.setFunc( object, index, value );
440   }
441   else
442   {
443     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
444     if ( base )
445     {
446       GetImplementation(base).SetProperty( object, index, value );
447     }
448     else
449     {
450       DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as ProxyObject
451     }
452   }
453 }
454
455 void TypeInfo::SetProperty( BaseObject *object, const std::string& name, const Property::Value& value )
456 {
457   RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
458                                                     PropertyNameFinder< RegisteredPropertyPair >( name ) );
459   if ( iter != mRegisteredProperties.end() )
460   {
461     DALI_ASSERT_ALWAYS( iter->second.setFunc && "Trying to write to a read-only property" );
462     iter->second.setFunc( object, iter->first, value );
463   }
464   else
465   {
466     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
467     if ( base )
468     {
469       GetImplementation(base).SetProperty( object, name, value );
470     }
471     else
472     {
473       DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
474     }
475   }
476 }
477
478 Property::Value TypeInfo::GetProperty( const BaseObject *object, Property::Index index )
479 {
480   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
481                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
482   if( iter != mRegisteredProperties.end() )
483   {
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 );
486   }
487
488   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
489   if ( base )
490   {
491     return GetImplementation( base ).GetProperty( object, index );
492   }
493
494   DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as ProxyObject
495
496   return Property::Value();
497 }
498
499 Property::Value TypeInfo::GetProperty( const BaseObject *object, const std::string& name )
500 {
501   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
502                                                           PropertyNameFinder< RegisteredPropertyPair >( name ) );
503   if( iter != mRegisteredProperties.end() )
504   {
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 );
507   }
508
509   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
510   if ( base )
511   {
512     return GetImplementation( base ).GetProperty( object, name );
513   }
514
515   DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
516
517   return Property::Value();
518 }
519
520 } // namespace Internal
521
522 } // namespace Dali