Ensure Animatable component properties can be animated
[platform/core/uifw/dali-core.git] / dali / internal / event / common / type-info-impl.cpp
1 /*
2  * Copyright (c) 2017 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   if ( ! mRegisteredProperties.empty() )
321   {
322     indices.Reserve( indices.Size() + mRegisteredProperties.size() );
323
324     const RegisteredPropertyContainer::const_iterator endIter = mRegisteredProperties.end();
325     for ( RegisteredPropertyContainer::const_iterator iter = mRegisteredProperties.begin(); iter != endIter; ++iter )
326     {
327       indices.PushBack( iter->first );
328     }
329   }
330 }
331
332 const std::string& TypeInfo::GetPropertyName( Property::Index index ) const
333 {
334   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
335                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
336
337   if ( iter != mRegisteredProperties.end() )
338   {
339     return iter->second.name;
340   }
341
342   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
343   if ( base )
344   {
345     return GetImplementation(base).GetPropertyName( index );
346   }
347
348   DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
349 }
350
351 void TypeInfo::AddActionFunction( const std::string &actionName, Dali::TypeInfo::ActionFunction function )
352 {
353   if( NULL == function)
354   {
355     DALI_LOG_WARNING("Action function is empty\n");
356   }
357   else
358   {
359     ActionContainer::iterator iter = std::find_if(mActions.begin(), mActions.end(),
360                                                   PairFinder<std::string, ActionPair>(actionName));
361
362     if( iter == mActions.end() )
363     {
364       mActions.push_back( ActionPair( actionName, function ) );
365     }
366     else
367     {
368       DALI_LOG_WARNING("Action already exists in TypeRegistry Type\n", actionName.c_str());
369     }
370   }
371 }
372
373 void TypeInfo::AddConnectorFunction( const std::string& signalName, Dali::TypeInfo::SignalConnectorFunction function )
374 {
375   if( NULL == function)
376   {
377     DALI_LOG_WARNING("Connector function is empty\n");
378   }
379   else
380   {
381     ConnectorContainer::iterator iter = find_if( mSignalConnectors.begin(), mSignalConnectors.end(),
382                                                    PairFinder<std::string, ConnectionPair>(signalName) );
383
384     if( iter == mSignalConnectors.end() )
385     {
386       mSignalConnectors.push_back( ConnectionPair( signalName, function ) );
387     }
388     else
389     {
390       DALI_LOG_WARNING("Signal name already exists in TypeRegistry Type for signal connector function\n", signalName.c_str());
391     }
392   }
393 }
394
395 void TypeInfo::AddProperty( const std::string& name, Property::Index index, Property::Type type, Dali::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc )
396 {
397   // The setter can be empty as a property can be read-only.
398
399   if ( NULL == getFunc )
400   {
401     DALI_ASSERT_ALWAYS( ! "GetProperty Function is empty" );
402   }
403   else
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, setFunc, getFunc, 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
419 void TypeInfo::AddProperty( const std::string& name, Property::Index index, Property::Type type, Dali::CSharpTypeInfo::SetPropertyFunction setFunc, Dali::CSharpTypeInfo::GetPropertyFunction getFunc)
420 {
421
422   // The setter can be empty as a property can be read-only.
423
424   if ( NULL == getFunc )
425   {
426     DALI_ASSERT_ALWAYS( ! "GetProperty Function is empty" );
427   }
428   else
429   {
430     RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
431                                                           PairFinder< Property::Index, RegisteredPropertyPair>(index) );
432
433     if ( iter == mRegisteredProperties.end() )
434     {
435       mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, setFunc, getFunc, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
436     }
437     else
438     {
439       DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
440     }
441   }
442
443 }
444
445
446 void TypeInfo::AddAnimatableProperty( const std::string& name, Property::Index index, Property::Type type )
447 {
448   RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
449                                                         PairFinder< Property::Index, RegisteredPropertyPair>(index) );
450
451   if ( iter == mRegisteredProperties.end() )
452   {
453     mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
454   }
455   else
456   {
457     DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
458   }
459 }
460
461 void TypeInfo::AddAnimatableProperty( const std::string& name, Property::Index index, const Property::Value& defaultValue )
462 {
463   RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
464                                                         PairFinder< Property::Index, RegisteredPropertyPair>(index) );
465
466   if ( iter == mRegisteredProperties.end() )
467   {
468     mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( defaultValue.GetType(), name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
469     mPropertyDefaultValues.push_back( PropertyDefaultValuePair( index, defaultValue ) );
470   }
471   else
472   {
473     DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
474   }
475 }
476
477 void TypeInfo::AddAnimatablePropertyComponent( const std::string& name, Property::Index index, Property::Index baseIndex, unsigned int componentIndex )
478 {
479   Property::Type type = GetPropertyType( baseIndex );
480   DALI_ASSERT_ALWAYS( ( type == Property::VECTOR2 || type == Property::VECTOR3 || type == Property::VECTOR4 ) && "Base property does not support component" );
481
482   bool success = false;
483
484   RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
485                                                         PairFinder< Property::Index, RegisteredPropertyPair>(index) );
486
487   if ( iter == mRegisteredProperties.end() )
488   {
489     iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
490                     PropertyComponentFinder< RegisteredPropertyPair >( baseIndex, componentIndex ) );
491
492     if ( iter == mRegisteredProperties.end() )
493     {
494       mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, name, baseIndex, componentIndex ) ) );
495       success = true;
496     }
497   }
498
499   DALI_ASSERT_ALWAYS( success && "Property component already registered" );
500 }
501
502 void TypeInfo::AddChildProperty( const std::string& name, Property::Index index, Property::Type type )
503 {
504   RegisteredPropertyContainer::iterator iter = find_if( mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(),
505                                                         PairFinder< Property::Index, RegisteredPropertyPair>(index) );
506
507   if ( iter == mRegisteredChildProperties.end() )
508   {
509     mRegisteredChildProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
510   }
511   else
512   {
513     DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
514   }
515 }
516
517 size_t TypeInfo::GetPropertyCount() const
518 {
519   size_t count( mRegisteredProperties.size() );
520
521   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
522   while ( base )
523   {
524     const TypeInfo& baseImpl( GetImplementation(base) );
525     count += baseImpl.mRegisteredProperties.size();
526     base = TypeRegistry::Get()->GetTypeInfo( baseImpl.mBaseTypeName );
527   }
528
529   return count;
530 }
531
532 Property::Index TypeInfo::GetPropertyIndex( const std::string& name ) const
533 {
534   Property::Index index = Property::INVALID_INDEX;
535
536   // Slow but should not be done that often
537   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
538                                                           PropertyNameFinder< RegisteredPropertyPair >( name ) );
539
540   if ( iter != mRegisteredProperties.end() )
541   {
542     index = iter->first;
543   }
544   else
545   {
546     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
547     if ( base )
548     {
549       index = GetImplementation(base).GetPropertyIndex( name );
550     }
551   }
552
553   return index;
554 }
555
556 Property::Index TypeInfo::GetBasePropertyIndex( Property::Index index ) const
557 {
558   Property::Index basePropertyIndex = Property::INVALID_INDEX;
559
560   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
561                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
562
563   if ( iter != mRegisteredProperties.end() )
564   {
565     basePropertyIndex = iter->second.basePropertyIndex;
566   }
567   else
568   {
569     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
570     if ( base )
571     {
572       basePropertyIndex = GetImplementation(base).GetBasePropertyIndex( index );
573     }
574   }
575
576   return basePropertyIndex;
577 }
578
579 int TypeInfo::GetComponentIndex( Property::Index index ) const
580 {
581   int componentIndex = Property::INVALID_COMPONENT_INDEX;
582
583   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
584                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
585
586   if ( iter != mRegisteredProperties.end() )
587   {
588     componentIndex = iter->second.componentIndex;
589   }
590   else
591   {
592     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
593     if ( base )
594     {
595       componentIndex = GetImplementation(base).GetComponentIndex( index );
596     }
597   }
598
599   return componentIndex;
600 }
601
602 Property::Index TypeInfo::GetChildPropertyIndex( const std::string& name ) const
603 {
604   Property::Index index = Property::INVALID_INDEX;
605
606   // Slow but should not be done that often
607   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(),
608                                                           PropertyNameFinder< RegisteredPropertyPair >( name ) );
609
610   if ( iter != mRegisteredChildProperties.end() )
611   {
612     index = iter->first;
613   }
614   else
615   {
616     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
617     if ( base )
618     {
619       index = GetImplementation(base).GetChildPropertyIndex( name );
620     }
621   }
622
623   return index;
624 }
625
626 const std::string& TypeInfo::GetChildPropertyName( Property::Index index ) const
627 {
628   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(),
629                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
630
631   if ( iter != mRegisteredChildProperties.end() )
632   {
633     return iter->second.name;
634   }
635
636   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
637   if ( base )
638   {
639     return GetImplementation(base).GetChildPropertyName( index );
640   }
641
642   DALI_LOG_WARNING("Cannot find property index");
643
644   static std::string emptyString;
645   return emptyString;
646 }
647
648 Property::Type TypeInfo::GetChildPropertyType( Property::Index index ) const
649 {
650   Property::Type type( Property::NONE );
651
652   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredChildProperties.begin(), mRegisteredChildProperties.end(),
653                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
654
655   if ( iter != mRegisteredChildProperties.end() )
656   {
657     type = iter->second.type;
658   }
659   else
660   {
661     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
662     if ( base )
663     {
664       type = GetImplementation(base).GetChildPropertyType( index );
665     }
666     else
667     {
668       DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
669     }
670   }
671
672   return type;
673 }
674
675 bool TypeInfo::IsPropertyWritable( Property::Index index ) const
676 {
677   bool writable( false );
678
679   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
680                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
681
682   if ( iter != mRegisteredProperties.end() )
683   {
684     if( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
685     {
686       writable = true; // animatable property is writable
687     }
688     else
689     {
690       writable = iter->second.setFunc ? true : false;
691     }
692   }
693   else
694   {
695     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
696     if ( base )
697     {
698       writable = GetImplementation(base).IsPropertyWritable( index );
699     }
700     else
701     {
702       DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
703     }
704   }
705
706   return writable;
707 }
708
709 Property::Type TypeInfo::GetPropertyType( Property::Index index ) const
710 {
711   Property::Type type( Property::NONE );
712
713   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
714                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
715
716   if ( iter != mRegisteredProperties.end() )
717   {
718     if( iter->second.componentIndex == Property::INVALID_COMPONENT_INDEX )
719     {
720       type = iter->second.type;
721     }
722     else
723     {
724       // If component index is set, then we should return FLOAT
725       type = Property::FLOAT;
726     }
727   }
728   else
729   {
730     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
731     if ( base )
732     {
733       type = GetImplementation(base).GetPropertyType( index );
734     }
735     else
736     {
737       DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
738     }
739   }
740
741   return type;
742 }
743
744 Property::Value TypeInfo::GetPropertyDefaultValue( Property::Index index ) const
745 {
746   PropertyDefaultValueContainer::const_iterator iter = find_if( mPropertyDefaultValues.begin(), mPropertyDefaultValues.end(),
747                                                     PairFinder< Property::Index, PropertyDefaultValuePair >( index ) );
748   if( iter !=  mPropertyDefaultValues.end() )
749   {
750     return iter->second;
751   }
752   else
753   {
754     return Property::Value( GetPropertyType( index ) );
755   }
756 }
757
758 void TypeInfo::SetProperty( BaseObject *object, Property::Index index, const Property::Value& value ) const
759 {
760   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
761                                                               PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
762   if ( iter != mRegisteredProperties.end() )
763   {
764     if( iter->second.setFunc )
765     {
766       if( mCSharpType )
767       {
768         // CSharp wants a property name not an index
769         const std::string& name = (iter->second).name;
770
771         iter->second.cSharpSetFunc( object,name.c_str(), const_cast< Property::Value* >(&value) );
772       }
773       else
774       {
775         iter->second.setFunc( object, index, value );
776       }
777     }
778   }
779   else
780   {
781     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
782     if ( base )
783     {
784       GetImplementation(base).SetProperty( object, index, value );
785     }
786     else
787     {
788       DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
789     }
790   }
791 }
792
793 void TypeInfo::SetProperty( BaseObject *object, const std::string& name, const Property::Value& value ) const
794 {
795   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
796                                                               PropertyNameFinder< RegisteredPropertyPair >( name ) );
797   if ( iter != mRegisteredProperties.end() )
798   {
799     DALI_ASSERT_ALWAYS( iter->second.setFunc && "Trying to write to a read-only property" );
800
801     if( mCSharpType )
802     {
803       // CSharp wants a property name not an index
804       iter->second.cSharpSetFunc( object,name.c_str(), const_cast< Property::Value* >(&value ));
805     }
806     else
807     {
808       iter->second.setFunc( object, iter->first, value );
809     }
810   }
811   else
812   {
813     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
814     if ( base )
815     {
816       GetImplementation(base).SetProperty( object, name, value );
817     }
818     else
819     {
820       DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
821     }
822   }
823 }
824
825 Property::Value TypeInfo::GetProperty( const BaseObject *object, Property::Index index ) const
826 {
827   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
828                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
829   if( iter != mRegisteredProperties.end() )
830   {
831     if( mCSharpType ) // using csharp property get which returns a pointer to a Property::Value
832     {
833       // CSharp wants a property name not an index
834       // CSharp callback can't return an object by value, it can only return a pointer
835       // CSharp has ownership of the pointer contents, which is fine because we are returning by from this function by value
836       const std::string& name = (iter->second).name;
837
838       return *( iter->second.cSharpGetFunc( const_cast< BaseObject* >( object ), name.c_str()) );
839
840     }
841     else
842     {
843       // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
844       return iter->second.getFunc( const_cast< BaseObject* >( object ), index );
845     }
846   }
847
848   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
849   if ( base )
850   {
851     return GetImplementation( base ).GetProperty( object, index );
852   }
853
854   DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
855 }
856
857 Property::Value TypeInfo::GetProperty( const BaseObject *object, const std::string& name ) const
858 {
859   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
860                                                             PropertyNameFinder< RegisteredPropertyPair >( name ) );
861
862
863
864   if( iter != mRegisteredProperties.end() )
865   {
866     if( mCSharpType ) // using csharp property get which returns a pointer to a Property::Value
867     {
868        // CSharp wants a property name not an index
869        // CSharp callback can't return an object by value, it can only return a pointer
870        // CSharp has ownership of the pointer contents, which is fine because we are returning by from this function by value
871        return *( iter->second.cSharpGetFunc( const_cast< BaseObject* >( object ), name.c_str() ));
872
873     }
874     else
875     {
876       // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
877       return iter->second.getFunc( const_cast< BaseObject* >( object ), iter->first );
878     }
879   }
880
881   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
882   if ( base )
883   {
884     return GetImplementation( base ).GetProperty( object, name );
885   }
886
887   DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
888 }
889
890 } // namespace Internal
891
892 } // namespace Dali