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