Remove std::vector from public api
[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 std::string TypeInfo::GetPropertyName(size_t index) const
296 {
297   std::string name;
298   Property::IndexContainer indices;
299
300   GetPropertyIndices(indices);
301
302   if( index < indices.Size() )
303   {
304     name = GetPropertyName( indices[index] );
305   }
306
307   return name;
308 }
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", 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", 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::AddAnimatableProperty( const std::string& name, Property::Index index, Property::Type type )
420 {
421   RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
422                                                         PairFinder< Property::Index, RegisteredPropertyPair>(index) );
423
424   if ( iter == mRegisteredProperties.end() )
425   {
426     mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, NULL, NULL, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
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 void TypeInfo::SetProperty( BaseObject *object, Property::Index index, const Property::Value& value ) const
606 {
607   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
608                                                               PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
609   if ( iter != mRegisteredProperties.end() )
610   {
611     if( iter->second.setFunc )
612     {
613       iter->second.setFunc( object, index, value );
614     }
615   }
616   else
617   {
618     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
619     if ( base )
620     {
621       GetImplementation(base).SetProperty( object, index, value );
622     }
623     else
624     {
625       DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
626     }
627   }
628 }
629
630 void TypeInfo::SetProperty( BaseObject *object, const std::string& name, const Property::Value& value ) const
631 {
632   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
633                                                               PropertyNameFinder< RegisteredPropertyPair >( name ) );
634   if ( iter != mRegisteredProperties.end() )
635   {
636     DALI_ASSERT_ALWAYS( iter->second.setFunc && "Trying to write to a read-only property" );
637     iter->second.setFunc( object, iter->first, value );
638   }
639   else
640   {
641     Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
642     if ( base )
643     {
644       GetImplementation(base).SetProperty( object, name, value );
645     }
646     else
647     {
648       DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
649     }
650   }
651 }
652
653 Property::Value TypeInfo::GetProperty( const BaseObject *object, Property::Index index ) const
654 {
655   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
656                                                           PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
657   if( iter != mRegisteredProperties.end() )
658   {
659     // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
660     return iter->second.getFunc( const_cast< BaseObject* >( object ), index );
661   }
662
663   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
664   if ( base )
665   {
666     return GetImplementation( base ).GetProperty( object, index );
667   }
668
669   DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
670 }
671
672 Property::Value TypeInfo::GetProperty( const BaseObject *object, const std::string& name ) const
673 {
674   RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
675                                                           PropertyNameFinder< RegisteredPropertyPair >( name ) );
676   if( iter != mRegisteredProperties.end() )
677   {
678     // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
679     return iter->second.getFunc( const_cast< BaseObject* >( object ), iter->first );
680   }
681
682   Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
683   if ( base )
684   {
685     return GetImplementation( base ).GetProperty( object, name );
686   }
687
688   DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
689 }
690
691 } // namespace Internal
692
693 } // namespace Dali