Merge changes I523a4ff5,Ic7d369c0 into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / event / common / type-info-impl.cpp
1 /*
2  * Copyright (c) 2015 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 /**
78  * Functor to find a matching property component index
79  */
80 template <typename T>
81 struct PropertyComponentFinder
82 {
83   PropertyComponentFinder( Dali::Property::Index basePropertyIndex, const int find )
84   : mBasePropertyIndex( basePropertyIndex ),
85     mFind( find )
86   {
87   }
88
89   bool operator()(const T &p) const
90   {
91     return ( p.second.basePropertyIndex == mBasePropertyIndex && p.second.componentIndex == mFind );
92   }
93
94 private:
95
96   Dali::Property::Index mBasePropertyIndex;
97   const int mFind;
98 };
99
100 } // namespace anon
101
102 namespace Dali
103 {
104
105 namespace Internal
106 {
107
108 TypeInfo::TypeInfo(const std::string &name, const std::string &baseTypeName, Dali::TypeInfo::CreateFunction creator)
109   : mTypeName(name), mBaseTypeName(baseTypeName), mCreate(creator)
110 {
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");
113 }
114
115 TypeInfo::~TypeInfo()
116 {
117 }
118
119 BaseHandle TypeInfo::CreateInstance() const
120 {
121   BaseHandle ret;
122
123   if(mCreate)
124   {
125     ret = mCreate();
126
127     if ( ret )
128     {
129       BaseObject& handle = ret.GetBaseObject();
130       Object *object = dynamic_cast<Internal::Object*>(&handle);
131
132       if ( object )
133       {
134         object->SetTypeInfo( this );
135       }
136     }
137   }
138   return ret;
139 }
140
141   bool TypeInfo::DoActionTo(BaseObject *object, const std::string &actionName, const Property::Map &properties)
142 {
143   bool done = false;
144
145   ActionContainer::iterator iter = find_if(mActions.begin(), mActions.end(), PairFinder<std::string, ActionPair>(actionName));
146
147   if( iter != mActions.end() )
148   {
149     done = (iter->second)(object, actionName, properties);
150   }
151   else
152   {
153     DALI_LOG_WARNING("Type '%s' cannot do action '%s'\n", mTypeName.c_str(), actionName.c_str());
154   }
155
156   if(!done)
157   {
158     Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
159     while( base )
160     {
161       done = GetImplementation(base).DoActionTo(object, actionName, properties);
162       if( done )
163       {
164         break;
165       }
166       base =  Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
167     }
168   }
169
170   return done;
171 }
172
173 bool TypeInfo::ConnectSignal( BaseObject* object, ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functor )
174 {
175   bool connected( false );
176
177   ConnectorContainer::iterator iter = find_if( mSignalConnectors.begin(), mSignalConnectors.end(),
178                                                  PairFinder<std::string, ConnectionPair>(signalName) );
179
180   if( iter != mSignalConnectors.end() )
181   {
182     connected = (iter->second)( object, connectionTracker, signalName, functor );
183   }
184
185   return connected;
186 }
187
188 const std::string& TypeInfo::GetName() const
189 {
190   return mTypeName;
191 }
192
193 const std::string& TypeInfo::GetBaseName() const
194 {
195   return mBaseTypeName;
196 }
197
198 Dali::TypeInfo::CreateFunction TypeInfo::GetCreator() const
199 {
200   return mCreate;
201 }
202
203 size_t TypeInfo::GetActionCount() const
204 {
205   size_t count = mActions.size();
206
207   Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
208   while( base )
209   {
210     count += GetImplementation(base).mActions.size();
211     base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
212   }
213
214   return count;
215 }
216
217 std::string TypeInfo::GetActionName(size_t index) const
218 {
219   std::string name;
220
221   if( index < mActions.size() )
222   {
223     name = mActions[index].first;
224   }
225   else
226   {
227     size_t count = mActions.size();
228
229     Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
230     while( base )
231     {
232       size_t baseCount = GetImplementation(base).mActions.size();
233
234       if( index < count + baseCount )
235       {
236         name = GetImplementation(base).mActions[ index - count ].first;
237         break;
238       }
239
240       count += baseCount;
241
242       base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
243     }
244   }
245
246   return name;
247 }
248
249 size_t TypeInfo::GetSignalCount() const
250 {
251   size_t count = mSignalConnectors.size();
252
253   Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
254   while( base )
255   {
256     count += GetImplementation(base).mSignalConnectors.size();
257     base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
258   }
259
260   return count;
261 }
262
263 std::string TypeInfo::GetSignalName(size_t index) const
264 {
265   std::string name;
266
267   if( index < mSignalConnectors.size() )
268   {
269     name = mSignalConnectors[index].first;
270   }
271   else
272   {
273     size_t count = mSignalConnectors.size();
274
275     Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
276     while( base )
277     {
278       size_t baseCount = GetImplementation(base).mSignalConnectors.size();
279
280       if( index < count + baseCount )
281       {
282         name = GetImplementation(base).mSignalConnectors[ index - count ].first;
283         break;
284       }
285
286       count += baseCount;
287
288       base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
289     }
290   }
291
292   return name;
293 }
294
295 void TypeInfo::GetPropertyIndices( Property::IndexContainer& indices ) const
296 {
297   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
298   if ( base )
299   {
300     const TypeInfo& baseImpl( GetImplementation( base ) );
301     baseImpl.GetPropertyIndices( indices );
302   }
303
304   if ( ! mRegisteredProperties.empty() )
305   {
306     indices.Reserve( indices.Size() + mRegisteredProperties.size() );
307
308     const RegisteredPropertyContainer::const_iterator endIter = mRegisteredProperties.end();
309     for ( RegisteredPropertyContainer::const_iterator iter = mRegisteredProperties.begin(); iter != endIter; ++iter )
310     {
311       indices.PushBack( iter->first );
312     }
313   }
314 }
315
316 const std::string& TypeInfo::GetPropertyName( Property::Index index ) const
317 {
318   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
319                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
320
321   if ( iter != mRegisteredProperties.end() )
322   {
323     return iter->second.name;
324   }
325
326   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
327   if ( base )
328   {
329     return GetImplementation(base).GetPropertyName( index );
330   }
331
332   DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
333 }
334
335 void TypeInfo::AddActionFunction( const std::string &actionName, Dali::TypeInfo::ActionFunction function )
336 {
337   if( NULL == function)
338   {
339     DALI_LOG_WARNING("Action function is empty\n");
340   }
341   else
342   {
343     ActionContainer::iterator iter = std::find_if(mActions.begin(), mActions.end(),
344                                                   PairFinder<std::string, ActionPair>(actionName));
345
346     if( iter == mActions.end() )
347     {
348       mActions.push_back( ActionPair( actionName, function ) );
349     }
350     else
351     {
352       DALI_LOG_WARNING("Action already exists in TypeRegistry Type", actionName.c_str());
353     }
354   }
355 }
356
357 void TypeInfo::AddConnectorFunction( const std::string& signalName, Dali::TypeInfo::SignalConnectorFunction function )
358 {
359   if( NULL == function)
360   {
361     DALI_LOG_WARNING("Connector function is empty\n");
362   }
363   else
364   {
365     ConnectorContainer::iterator iter = find_if( mSignalConnectors.begin(), mSignalConnectors.end(),
366                                                    PairFinder<std::string, ConnectionPair>(signalName) );
367
368     if( iter == mSignalConnectors.end() )
369     {
370       mSignalConnectors.push_back( ConnectionPair( signalName, function ) );
371     }
372     else
373     {
374       DALI_LOG_WARNING("Signal name already exists in TypeRegistry Type for signal connector function", signalName.c_str());
375     }
376   }
377 }
378
379 void TypeInfo::AddProperty( const std::string& name, Property::Index index, Property::Type type, Dali::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc )
380 {
381   // The setter can be empty as a property can be read-only.
382
383   if ( NULL == getFunc )
384   {
385     DALI_ASSERT_ALWAYS( ! "GetProperty Function is empty" );
386   }
387   else
388   {
389     RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
390                                                           PairFinder< Property::Index, RegisteredPropertyPair>(index) );
391
392     if ( iter == mRegisteredProperties.end() )
393     {
394       mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, setFunc, getFunc, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
395     }
396     else
397     {
398       DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
399     }
400   }
401 }
402
403 void TypeInfo::AddAnimatableProperty( const std::string& name, Property::Index index, Property::Type type )
404 {
405   RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
406                                                         PairFinder< Property::Index, RegisteredPropertyPair>(index) );
407
408   if ( iter == mRegisteredProperties.end() )
409   {
410     mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, NULL, NULL, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
411   }
412   else
413   {
414     DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
415   }
416 }
417
418 void TypeInfo::AddAnimatableProperty( const std::string& name, Property::Index index, const Property::Value& defaultValue )
419 {
420   RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
421                                                         PairFinder< Property::Index, RegisteredPropertyPair>(index) );
422
423   if ( iter == mRegisteredProperties.end() )
424   {
425     mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( defaultValue.GetType(), NULL, NULL, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
426     mPropertyDefaultValues.push_back( PropertyDefaultValuePair( index, defaultValue ) );
427   }
428   else
429   {
430     DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
431   }
432 }
433
434 void TypeInfo::AddAnimatablePropertyComponent( const std::string& name, Property::Index index, Property::Index baseIndex, unsigned int componentIndex )
435 {
436   Property::Type type = GetPropertyType( baseIndex );
437   DALI_ASSERT_ALWAYS( ( type == Property::VECTOR2 || type == Property::VECTOR3 || type == Property::VECTOR4 ) && "Base property does not support component" );
438
439   bool success = false;
440
441   RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
442                                                         PairFinder< Property::Index, RegisteredPropertyPair>(index) );
443
444   if ( iter == mRegisteredProperties.end() )
445   {
446     iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
447                     PropertyComponentFinder< RegisteredPropertyPair >( baseIndex, componentIndex ) );
448
449     if ( iter == mRegisteredProperties.end() )
450     {
451       mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, NULL, NULL, name, baseIndex, componentIndex ) ) );
452       success = true;
453     }
454   }
455
456   DALI_ASSERT_ALWAYS( success && "Property component already registered" );
457 }
458
459 size_t TypeInfo::GetPropertyCount() const
460 {
461   size_t count( mRegisteredProperties.size() );
462
463   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
464   while ( base )
465   {
466     const TypeInfo& baseImpl( GetImplementation(base) );
467     count += baseImpl.mRegisteredProperties.size();
468     base = TypeRegistry::Get()->GetTypeInfo( baseImpl.mBaseTypeName );
469   }
470
471   return count;
472 }
473
474 Property::Index TypeInfo::GetPropertyIndex( const std::string& name ) const
475 {
476   Property::Index index = Property::INVALID_INDEX;
477
478   // Slow but should not be done that often
479   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
480                                                           PropertyNameFinder< RegisteredPropertyPair >( name ) );
481
482   if ( iter != mRegisteredProperties.end() )
483   {
484     index = iter->first;
485   }
486   else
487   {
488     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
489     if ( base )
490     {
491       index = GetImplementation(base).GetPropertyIndex( name );
492     }
493   }
494
495   return index;
496 }
497
498 Property::Index TypeInfo::GetBasePropertyIndex( Property::Index index ) const
499 {
500   Property::Index basePropertyIndex = Property::INVALID_INDEX;
501
502   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
503                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
504
505   if ( iter != mRegisteredProperties.end() )
506   {
507     basePropertyIndex = iter->second.basePropertyIndex;
508   }
509   else
510   {
511     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
512     if ( base )
513     {
514       basePropertyIndex = GetImplementation(base).GetBasePropertyIndex( index );
515     }
516   }
517
518   return basePropertyIndex;
519 }
520
521 int TypeInfo::GetComponentIndex( Property::Index index ) const
522 {
523   int componentIndex = Property::INVALID_COMPONENT_INDEX;
524
525   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
526                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
527
528   if ( iter != mRegisteredProperties.end() )
529   {
530     componentIndex = iter->second.componentIndex;
531   }
532   else
533   {
534     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
535     if ( base )
536     {
537       componentIndex = GetImplementation(base).GetComponentIndex( index );
538     }
539   }
540
541   return componentIndex;
542 }
543
544 bool TypeInfo::IsPropertyWritable( Property::Index index ) const
545 {
546   bool writable( false );
547
548   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
549                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
550
551   if ( iter != mRegisteredProperties.end() )
552   {
553     if( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
554     {
555       writable = true; // animatable property is writable
556     }
557     else
558     {
559       writable = iter->second.setFunc ? true : false;
560     }
561   }
562   else
563   {
564     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
565     if ( base )
566     {
567       writable = GetImplementation(base).IsPropertyWritable( index );
568     }
569     else
570     {
571       DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
572     }
573   }
574
575   return writable;
576 }
577
578 Property::Type TypeInfo::GetPropertyType( Property::Index index ) const
579 {
580   Property::Type type( Property::NONE );
581
582   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
583                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
584
585   if ( iter != mRegisteredProperties.end() )
586   {
587     type = iter->second.type;
588   }
589   else
590   {
591     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
592     if ( base )
593     {
594       type = GetImplementation(base).GetPropertyType( index );
595     }
596     else
597     {
598       DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
599     }
600   }
601
602   return type;
603 }
604
605 Property::Value TypeInfo::GetPropertyDefaultValue( Property::Index index ) const
606 {
607   PropertyDefaultValueContainer::const_iterator iter = find_if( mPropertyDefaultValues.begin(), mPropertyDefaultValues.end(),
608                                                     PairFinder< Property::Index, PropertyDefaultValuePair >( index ) );
609   if( iter !=  mPropertyDefaultValues.end() )
610   {
611     return iter->second;
612   }
613   else
614   {
615     return Property::Value( GetPropertyType( index ) );
616   }
617 }
618
619 void TypeInfo::SetProperty( BaseObject *object, Property::Index index, const Property::Value& value ) const
620 {
621   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
622                                                               PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
623   if ( iter != mRegisteredProperties.end() )
624   {
625     if( iter->second.setFunc )
626     {
627       iter->second.setFunc( object, index, value );
628     }
629   }
630   else
631   {
632     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
633     if ( base )
634     {
635       GetImplementation(base).SetProperty( object, index, value );
636     }
637     else
638     {
639       DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
640     }
641   }
642 }
643
644 void TypeInfo::SetProperty( BaseObject *object, const std::string& name, const Property::Value& value ) const
645 {
646   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
647                                                               PropertyNameFinder< RegisteredPropertyPair >( name ) );
648   if ( iter != mRegisteredProperties.end() )
649   {
650     DALI_ASSERT_ALWAYS( iter->second.setFunc && "Trying to write to a read-only property" );
651     iter->second.setFunc( object, iter->first, value );
652   }
653   else
654   {
655     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
656     if ( base )
657     {
658       GetImplementation(base).SetProperty( object, name, value );
659     }
660     else
661     {
662       DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
663     }
664   }
665 }
666
667 Property::Value TypeInfo::GetProperty( const BaseObject *object, Property::Index index ) const
668 {
669   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
670                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
671   if( iter != mRegisteredProperties.end() )
672   {
673     // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
674     return iter->second.getFunc( const_cast< BaseObject* >( object ), index );
675   }
676
677   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
678   if ( base )
679   {
680     return GetImplementation( base ).GetProperty( object, index );
681   }
682
683   DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
684 }
685
686 Property::Value TypeInfo::GetProperty( const BaseObject *object, const std::string& name ) const
687 {
688   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
689                                                           PropertyNameFinder< RegisteredPropertyPair >( name ) );
690   if( iter != mRegisteredProperties.end() )
691   {
692     // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
693     return iter->second.getFunc( const_cast< BaseObject* >( object ), iter->first );
694   }
695
696   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
697   if ( base )
698   {
699     return GetImplementation( base ).GetProperty( object, name );
700   }
701
702   DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
703 }
704
705 } // namespace Internal
706
707 } // namespace Dali