Making DALi core internals typesafe using guaranteed types; uint8_t, uint32_t
[platform/core/uifw/dali-core.git] / dali / internal / event / common / type-info-impl.cpp
1 /*
2  * Copyright (c) 2018 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), mCSharpType(false), 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(const std::string &name, const std::string &baseTypeName, Dali::CSharpTypeInfo::CreateFunction creator)
116   : mTypeName(name), mBaseTypeName(baseTypeName), mCSharpType(true), mCSharpCreate(creator)
117 {
118   DALI_ASSERT_ALWAYS(!name.empty() && "Type info construction must have a name");
119   DALI_ASSERT_ALWAYS(!baseTypeName.empty() && "Type info construction must have a base type name");
120 }
121
122 TypeInfo::~TypeInfo()
123 {
124 }
125
126 BaseHandle TypeInfo::CreateInstance() const
127 {
128   BaseHandle ret;
129
130   if(mCreate)
131   {
132     if ( mCSharpType )
133     {
134       // CSharp currently only registers one create function for all custom controls
135       // it uses the type name to decide which one to create
136       ret = *mCSharpCreate( mTypeName.c_str() );
137     }
138     else
139     {
140       ret = mCreate();
141     }
142
143     if ( ret )
144     {
145       BaseObject& handle = ret.GetBaseObject();
146       Object *object = dynamic_cast<Internal::Object*>(&handle);
147
148       if ( object )
149       {
150         object->SetTypeInfo( this );
151       }
152     }
153   }
154   return ret;
155 }
156
157   bool TypeInfo::DoActionTo(BaseObject *object, const std::string &actionName, const Property::Map &properties)
158 {
159   bool done = false;
160
161   ActionContainer::iterator iter = find_if(mActions.begin(), mActions.end(), PairFinder<std::string, ActionPair>(actionName));
162
163   if( iter != mActions.end() )
164   {
165     done = (iter->second)(object, actionName, properties);
166   }
167   else
168   {
169     DALI_LOG_WARNING("Type '%s' cannot do action '%s'\n", mTypeName.c_str(), actionName.c_str());
170   }
171
172   if(!done)
173   {
174     Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
175     while( base )
176     {
177       done = GetImplementation(base).DoActionTo(object, actionName, properties);
178       if( done )
179       {
180         break;
181       }
182       base =  Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
183     }
184   }
185
186   return done;
187 }
188
189 bool TypeInfo::ConnectSignal( BaseObject* object, ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functor )
190 {
191   bool connected( false );
192
193   ConnectorContainer::iterator iter = find_if( mSignalConnectors.begin(), mSignalConnectors.end(),
194                                                  PairFinder<std::string, ConnectionPair>(signalName) );
195
196   if( iter != mSignalConnectors.end() )
197   {
198     connected = (iter->second)( object, connectionTracker, signalName, functor );
199   }
200
201   return connected;
202 }
203
204 const std::string& TypeInfo::GetName() const
205 {
206   return mTypeName;
207 }
208
209 const std::string& TypeInfo::GetBaseName() const
210 {
211   return mBaseTypeName;
212 }
213
214 Dali::TypeInfo::CreateFunction TypeInfo::GetCreator() const
215 {
216   return mCreate;
217 }
218
219 size_t TypeInfo::GetActionCount() const
220 {
221   size_t count = mActions.size();
222
223   Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
224   while( base )
225   {
226     count += GetImplementation(base).mActions.size();
227     base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
228   }
229
230   return count;
231 }
232
233 std::string TypeInfo::GetActionName(size_t index) const
234 {
235   std::string name;
236
237   if( index < mActions.size() )
238   {
239     name = mActions[index].first;
240   }
241   else
242   {
243     size_t count = mActions.size();
244
245     Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
246     while( base )
247     {
248       size_t baseCount = GetImplementation(base).mActions.size();
249
250       if( index < count + baseCount )
251       {
252         name = GetImplementation(base).mActions[ index - count ].first;
253         break;
254       }
255
256       count += baseCount;
257
258       base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
259     }
260   }
261
262   return name;
263 }
264
265 size_t TypeInfo::GetSignalCount() const
266 {
267   size_t count = mSignalConnectors.size();
268
269   Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
270   while( base )
271   {
272     count += GetImplementation(base).mSignalConnectors.size();
273     base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
274   }
275
276   return count;
277 }
278
279 std::string TypeInfo::GetSignalName(size_t index) const
280 {
281   std::string name;
282
283   if( index < mSignalConnectors.size() )
284   {
285     name = mSignalConnectors[index].first;
286   }
287   else
288   {
289     size_t count = mSignalConnectors.size();
290
291     Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
292     while( base )
293     {
294       size_t baseCount = GetImplementation(base).mSignalConnectors.size();
295
296       if( index < count + baseCount )
297       {
298         name = GetImplementation(base).mSignalConnectors[ index - count ].first;
299         break;
300       }
301
302       count += baseCount;
303
304       base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
305     }
306   }
307
308   return name;
309 }
310
311 void TypeInfo::GetPropertyIndices( Property::IndexContainer& indices ) const
312 {
313   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
314   if ( base )
315   {
316     const TypeInfo& baseImpl( GetImplementation( base ) );
317     baseImpl.GetPropertyIndices( indices );
318   }
319
320   AppendProperties( indices, mRegisteredProperties );
321 }
322
323 void TypeInfo::GetChildPropertyIndices( Property::IndexContainer& indices ) const
324 {
325   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
326   if ( base )
327   {
328     const TypeInfo& baseImpl( GetImplementation( base ) );
329     baseImpl.GetChildPropertyIndices( indices );
330   }
331
332   AppendProperties( indices, mRegisteredChildProperties );
333 }
334
335 /**
336  * Append the indices in RegisteredProperties to the given index container.
337  */
338 void TypeInfo::AppendProperties( Dali::Property::IndexContainer& indices,
339                                  const TypeInfo::RegisteredPropertyContainer& registeredProperties ) const
340 {
341   if ( ! registeredProperties.empty() )
342   {
343     indices.Reserve( indices.Size() + registeredProperties.size() );
344
345     for( auto&& elem : registeredProperties )
346     {
347       indices.PushBack( elem.first );
348     }
349   }
350 }
351
352 const std::string& TypeInfo::GetPropertyName( Property::Index index ) const
353 {
354   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
355                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
356
357   if ( iter != mRegisteredProperties.end() )
358   {
359     return iter->second.name;
360   }
361
362   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
363   if ( base )
364   {
365     return GetImplementation(base).GetPropertyName( index );
366   }
367
368   DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
369 }
370
371 void TypeInfo::AddActionFunction( const std::string &actionName, Dali::TypeInfo::ActionFunction function )
372 {
373   if( NULL == function)
374   {
375     DALI_LOG_WARNING("Action function is empty\n");
376   }
377   else
378   {
379     ActionContainer::iterator iter = std::find_if(mActions.begin(), mActions.end(),
380                                                   PairFinder<std::string, ActionPair>(actionName));
381
382     if( iter == mActions.end() )
383     {
384       mActions.push_back( ActionPair( actionName, function ) );
385     }
386     else
387     {
388       DALI_LOG_WARNING("Action already exists in TypeRegistry Type\n", actionName.c_str());
389     }
390   }
391 }
392
393 void TypeInfo::AddConnectorFunction( const std::string& signalName, Dali::TypeInfo::SignalConnectorFunction function )
394 {
395   if( NULL == function)
396   {
397     DALI_LOG_WARNING("Connector function is empty\n");
398   }
399   else
400   {
401     ConnectorContainer::iterator iter = find_if( mSignalConnectors.begin(), mSignalConnectors.end(),
402                                                    PairFinder<std::string, ConnectionPair>(signalName) );
403
404     if( iter == mSignalConnectors.end() )
405     {
406       mSignalConnectors.push_back( ConnectionPair( signalName, function ) );
407     }
408     else
409     {
410       DALI_LOG_WARNING("Signal name already exists in TypeRegistry Type for signal connector function\n", signalName.c_str());
411     }
412   }
413 }
414
415 void TypeInfo::AddProperty( const std::string& name, Property::Index index, Property::Type type, Dali::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc )
416 {
417   // The setter can be empty as a property can be read-only.
418
419   if ( NULL == getFunc )
420   {
421     DALI_ASSERT_ALWAYS( ! "GetProperty Function is empty" );
422   }
423   else
424   {
425     RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
426                                                           PairFinder< Property::Index, RegisteredPropertyPair>(index) );
427
428     if ( iter == mRegisteredProperties.end() )
429     {
430       mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, setFunc, getFunc, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
431     }
432     else
433     {
434       DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
435     }
436   }
437 }
438
439 void TypeInfo::AddProperty( const std::string& name, Property::Index index, Property::Type type, Dali::CSharpTypeInfo::SetPropertyFunction setFunc, Dali::CSharpTypeInfo::GetPropertyFunction getFunc)
440 {
441
442   // The setter can be empty as a property can be read-only.
443
444   if ( NULL == getFunc )
445   {
446     DALI_ASSERT_ALWAYS( ! "GetProperty Function is empty" );
447   }
448   else
449   {
450     RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
451                                                           PairFinder< Property::Index, RegisteredPropertyPair>(index) );
452
453     if ( iter == mRegisteredProperties.end() )
454     {
455       mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, setFunc, getFunc, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
456     }
457     else
458     {
459       DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
460     }
461   }
462
463 }
464
465
466 void TypeInfo::AddAnimatableProperty( const std::string& name, Property::Index index, Property::Type type )
467 {
468   RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
469                                                         PairFinder< Property::Index, RegisteredPropertyPair>(index) );
470
471   if ( iter == mRegisteredProperties.end() )
472   {
473     mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
474   }
475   else
476   {
477     DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
478   }
479 }
480
481 void TypeInfo::AddAnimatableProperty( const std::string& name, Property::Index index, const Property::Value& defaultValue )
482 {
483   RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
484                                                         PairFinder< Property::Index, RegisteredPropertyPair>(index) );
485
486   if ( iter == mRegisteredProperties.end() )
487   {
488     mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( defaultValue.GetType(), name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
489     mPropertyDefaultValues.push_back( PropertyDefaultValuePair( index, defaultValue ) );
490   }
491   else
492   {
493     DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
494   }
495 }
496
497 void TypeInfo::AddAnimatablePropertyComponent( const std::string& name, Property::Index index, Property::Index baseIndex, unsigned int componentIndex )
498 {
499   Property::Type type = GetPropertyType( baseIndex );
500   DALI_ASSERT_ALWAYS( ( type == Property::VECTOR2 || type == Property::VECTOR3 || type == Property::VECTOR4 ) && "Base property does not support component" );
501
502   bool success = false;
503
504   RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
505                                                         PairFinder< Property::Index, RegisteredPropertyPair>(index) );
506
507   if ( iter == mRegisteredProperties.end() )
508   {
509     iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
510                     PropertyComponentFinder< RegisteredPropertyPair >( baseIndex, componentIndex ) );
511
512     if ( iter == mRegisteredProperties.end() )
513     {
514       mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, name, baseIndex, componentIndex ) ) );
515       success = true;
516     }
517   }
518
519   DALI_ASSERT_ALWAYS( success && "Property component already registered" );
520 }
521
522 void TypeInfo::AddChildProperty( const std::string& name, Property::Index index, Property::Type type )
523 {
524   RegisteredPropertyContainer::iterator iter = find_if( mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(),
525                                                         PairFinder< Property::Index, RegisteredPropertyPair>(index) );
526
527   if ( iter == mRegisteredChildProperties.end() )
528   {
529     mRegisteredChildProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
530   }
531   else
532   {
533     DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
534   }
535 }
536
537 uint32_t TypeInfo::GetPropertyCount() const
538 {
539   uint32_t count = static_cast<uint32_t>( mRegisteredProperties.size() );
540
541   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
542   while ( base )
543   {
544     const TypeInfo& baseImpl( GetImplementation(base) );
545     count += static_cast<uint32_t>( baseImpl.mRegisteredProperties.size() );
546     base = TypeRegistry::Get()->GetTypeInfo( baseImpl.mBaseTypeName );
547   }
548
549   return count;
550 }
551
552 Property::Index TypeInfo::GetPropertyIndex( const std::string& name ) const
553 {
554   Property::Index index = Property::INVALID_INDEX;
555
556   // Slow but should not be done that often
557   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
558                                                           PropertyNameFinder< RegisteredPropertyPair >( name ) );
559
560   if ( iter != mRegisteredProperties.end() )
561   {
562     index = iter->first;
563   }
564   else
565   {
566     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
567     if ( base )
568     {
569       index = GetImplementation(base).GetPropertyIndex( name );
570     }
571   }
572
573   return index;
574 }
575
576 Property::Index TypeInfo::GetBasePropertyIndex( Property::Index index ) const
577 {
578   Property::Index basePropertyIndex = Property::INVALID_INDEX;
579
580   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
581                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
582
583   if ( iter != mRegisteredProperties.end() )
584   {
585     basePropertyIndex = iter->second.basePropertyIndex;
586   }
587   else
588   {
589     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
590     if ( base )
591     {
592       basePropertyIndex = GetImplementation(base).GetBasePropertyIndex( index );
593     }
594   }
595
596   return basePropertyIndex;
597 }
598
599 int TypeInfo::GetComponentIndex( Property::Index index ) const
600 {
601   int componentIndex = Property::INVALID_COMPONENT_INDEX;
602
603   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
604                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
605
606   if ( iter != mRegisteredProperties.end() )
607   {
608     componentIndex = iter->second.componentIndex;
609   }
610   else
611   {
612     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
613     if ( base )
614     {
615       componentIndex = GetImplementation(base).GetComponentIndex( index );
616     }
617   }
618
619   return componentIndex;
620 }
621
622 Property::Index TypeInfo::GetChildPropertyIndex( const std::string& name ) const
623 {
624   Property::Index index = Property::INVALID_INDEX;
625
626   // Slow but should not be done that often
627   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(),
628                                                           PropertyNameFinder< RegisteredPropertyPair >( name ) );
629
630   if ( iter != mRegisteredChildProperties.end() )
631   {
632     index = iter->first;
633   }
634   else
635   {
636     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
637     if ( base )
638     {
639       index = GetImplementation(base).GetChildPropertyIndex( name );
640     }
641   }
642
643   return index;
644 }
645
646 const std::string& TypeInfo::GetChildPropertyName( Property::Index index ) const
647 {
648   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(),
649                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
650
651   if ( iter != mRegisteredChildProperties.end() )
652   {
653     return iter->second.name;
654   }
655
656   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
657   if ( base )
658   {
659     return GetImplementation(base).GetChildPropertyName( index );
660   }
661
662   DALI_LOG_WARNING("Cannot find property index");
663
664   static std::string emptyString;
665   return emptyString;
666 }
667
668 Property::Type TypeInfo::GetChildPropertyType( Property::Index index ) const
669 {
670   Property::Type type( Property::NONE );
671
672   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(),
673                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
674
675   if ( iter != mRegisteredChildProperties.end() )
676   {
677     type = iter->second.type;
678   }
679   else
680   {
681     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
682     if ( base )
683     {
684       type = GetImplementation(base).GetChildPropertyType( index );
685     }
686     else
687     {
688       DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
689     }
690   }
691
692   return type;
693 }
694
695 bool TypeInfo::IsPropertyWritable( Property::Index index ) const
696 {
697   bool writable( false );
698
699   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
700                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
701
702   if ( iter != mRegisteredProperties.end() )
703   {
704     if( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
705     {
706       writable = true; // animatable property is writable
707     }
708     else
709     {
710       writable = iter->second.setFunc ? true : false;
711     }
712   }
713   else
714   {
715     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
716     if ( base )
717     {
718       writable = GetImplementation(base).IsPropertyWritable( index );
719     }
720     else
721     {
722       DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
723     }
724   }
725
726   return writable;
727 }
728
729 Property::Type TypeInfo::GetPropertyType( Property::Index index ) const
730 {
731   Property::Type type( Property::NONE );
732
733   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
734                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
735
736   if ( iter != mRegisteredProperties.end() )
737   {
738     if( iter->second.componentIndex == Property::INVALID_COMPONENT_INDEX )
739     {
740       type = iter->second.type;
741     }
742     else
743     {
744       // If component index is set, then we should return FLOAT
745       type = Property::FLOAT;
746     }
747   }
748   else
749   {
750     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
751     if ( base )
752     {
753       type = GetImplementation(base).GetPropertyType( index );
754     }
755     else
756     {
757       DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
758     }
759   }
760
761   return type;
762 }
763
764 Property::Value TypeInfo::GetPropertyDefaultValue( Property::Index index ) const
765 {
766   PropertyDefaultValueContainer::const_iterator iter = find_if( mPropertyDefaultValues.begin(), mPropertyDefaultValues.end(),
767                                                     PairFinder< Property::Index, PropertyDefaultValuePair >( index ) );
768   if( iter !=  mPropertyDefaultValues.end() )
769   {
770     return iter->second;
771   }
772   else
773   {
774     return Property::Value( GetPropertyType( index ) );
775   }
776 }
777
778 void TypeInfo::SetProperty( BaseObject *object, Property::Index index, const Property::Value& value ) const
779 {
780   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
781                                                               PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
782   if ( iter != mRegisteredProperties.end() )
783   {
784     if( iter->second.setFunc )
785     {
786       if( mCSharpType )
787       {
788         // CSharp wants a property name not an index
789         const std::string& name = (iter->second).name;
790
791         iter->second.cSharpSetFunc( object,name.c_str(), const_cast< Property::Value* >(&value) );
792       }
793       else
794       {
795         iter->second.setFunc( object, index, value );
796       }
797     }
798   }
799   else
800   {
801     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
802     if ( base )
803     {
804       GetImplementation(base).SetProperty( object, index, value );
805     }
806     else
807     {
808       DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
809     }
810   }
811 }
812
813 void TypeInfo::SetProperty( BaseObject *object, const std::string& name, const Property::Value& value ) const
814 {
815   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
816                                                               PropertyNameFinder< RegisteredPropertyPair >( name ) );
817   if ( iter != mRegisteredProperties.end() )
818   {
819     DALI_ASSERT_ALWAYS( iter->second.setFunc && "Trying to write to a read-only property" );
820
821     if( mCSharpType )
822     {
823       // CSharp wants a property name not an index
824       iter->second.cSharpSetFunc( object,name.c_str(), const_cast< Property::Value* >(&value ));
825     }
826     else
827     {
828       iter->second.setFunc( object, iter->first, value );
829     }
830   }
831   else
832   {
833     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
834     if ( base )
835     {
836       GetImplementation(base).SetProperty( object, name, value );
837     }
838     else
839     {
840       DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
841     }
842   }
843 }
844
845 Property::Value TypeInfo::GetProperty( const BaseObject *object, Property::Index index ) const
846 {
847   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
848                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
849   if( iter != mRegisteredProperties.end() )
850   {
851     if( mCSharpType ) // using csharp property get which returns a pointer to a Property::Value
852     {
853       // CSharp wants a property name not an index
854       // CSharp callback can't return an object by value, it can only return a pointer
855       // CSharp has ownership of the pointer contents, which is fine because we are returning by from this function by value
856       const std::string& name = (iter->second).name;
857
858       return *( iter->second.cSharpGetFunc( const_cast< BaseObject* >( object ), name.c_str()) );
859
860     }
861     else
862     {
863       // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
864       return iter->second.getFunc( const_cast< BaseObject* >( object ), index );
865     }
866   }
867
868   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
869   if ( base )
870   {
871     return GetImplementation( base ).GetProperty( object, index );
872   }
873
874   DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
875 }
876
877 Property::Value TypeInfo::GetProperty( const BaseObject *object, const std::string& name ) const
878 {
879   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
880                                                             PropertyNameFinder< RegisteredPropertyPair >( name ) );
881
882
883
884   if( iter != mRegisteredProperties.end() )
885   {
886     if( mCSharpType ) // using csharp property get which returns a pointer to a Property::Value
887     {
888        // CSharp wants a property name not an index
889        // CSharp callback can't return an object by value, it can only return a pointer
890        // CSharp has ownership of the pointer contents, which is fine because we are returning by from this function by value
891        return *( iter->second.cSharpGetFunc( const_cast< BaseObject* >( object ), name.c_str() ));
892
893     }
894     else
895     {
896       // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
897       return iter->second.getFunc( const_cast< BaseObject* >( object ), iter->first );
898     }
899   }
900
901   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
902   if ( base )
903   {
904     return GetImplementation( base ).GetProperty( object, name );
905   }
906
907   DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
908 }
909
910 } // namespace Internal
911
912 } // namespace Dali