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