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