Dali 3D User Interface Engine
type-info-impl.cpp
Go to the documentation of this file.
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
20 
21 // EXTERNAL INCLUDES
22 #include <algorithm> // std::find_if
23 #include <string>
24 
25 // INTERNAL INCLUDES
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 
59 template <typename T>
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 
80 template <typename T>
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 
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 
116 {
117 }
118 
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  {
159  while( base )
160  {
161  done = GetImplementation(base).DoActionTo(object, actionName, properties);
162  if( done )
163  {
164  break;
165  }
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 
199 {
200  return mCreate;
201 }
202 
204 {
205  size_t count = mActions.size();
206 
208  while( base )
209  {
210  count += GetImplementation(base).mActions.size();
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 
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 
243  }
244  }
245 
246  return name;
247 }
248 
250 {
251  size_t count = mSignalConnectors.size();
252 
254  while( base )
255  {
256  count += GetImplementation(base).mSignalConnectors.size();
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 
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 
289  }
290  }
291 
292  return name;
293 }
294 
296 {
298  if ( base )
299  {
300  const TypeInfo& baseImpl( GetImplementation( base ) );
301  baseImpl.GetPropertyIndices( indices );
302  }
303 
304  if ( ! mRegisteredProperties.empty() )
305  {
306  indices.Reserve( indices.Size() + mRegisteredProperties.size() );
307 
308  const RegisteredPropertyContainer::const_iterator endIter = mRegisteredProperties.end();
309  for ( RegisteredPropertyContainer::const_iterator iter = mRegisteredProperties.begin(); iter != endIter; ++iter )
310  {
311  indices.PushBack( iter->first );
312  }
313  }
314 }
315 
316 const std::string& TypeInfo::GetPropertyName( Property::Index index ) const
317 {
318  RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
319  PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
320 
321  if ( iter != mRegisteredProperties.end() )
322  {
323  return iter->second.name;
324  }
325 
327  if ( base )
328  {
329  return GetImplementation(base).GetPropertyName( index );
330  }
331 
332  DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
333 }
334 
335 void TypeInfo::AddActionFunction( const std::string &actionName, Dali::TypeInfo::ActionFunction function )
336 {
337  if( NULL == function)
338  {
339  DALI_LOG_WARNING("Action function is empty\n");
340  }
341  else
342  {
343  ActionContainer::iterator iter = std::find_if(mActions.begin(), mActions.end(),
344  PairFinder<std::string, ActionPair>(actionName));
345 
346  if( iter == mActions.end() )
347  {
348  mActions.push_back( ActionPair( actionName, function ) );
349  }
350  else
351  {
352  DALI_LOG_WARNING("Action already exists in TypeRegistry Type", actionName.c_str());
353  }
354  }
355 }
356 
357 void TypeInfo::AddConnectorFunction( const std::string& signalName, Dali::TypeInfo::SignalConnectorFunction function )
358 {
359  if( NULL == function)
360  {
361  DALI_LOG_WARNING("Connector function is empty\n");
362  }
363  else
364  {
365  ConnectorContainer::iterator iter = find_if( mSignalConnectors.begin(), mSignalConnectors.end(),
366  PairFinder<std::string, ConnectionPair>(signalName) );
367 
368  if( iter == mSignalConnectors.end() )
369  {
370  mSignalConnectors.push_back( ConnectionPair( signalName, function ) );
371  }
372  else
373  {
374  DALI_LOG_WARNING("Signal name already exists in TypeRegistry Type for signal connector function", signalName.c_str());
375  }
376  }
377 }
378 
380 {
381  // The setter can be empty as a property can be read-only.
382 
383  if ( NULL == getFunc )
384  {
385  DALI_ASSERT_ALWAYS( ! "GetProperty Function is empty" );
386  }
387  else
388  {
389  RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
390  PairFinder< Property::Index, RegisteredPropertyPair>(index) );
391 
392  if ( iter == mRegisteredProperties.end() )
393  {
395  }
396  else
397  {
398  DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
399  }
400  }
401 }
402 
403 void TypeInfo::AddAnimatableProperty( const std::string& name, Property::Index index, Property::Type type )
404 {
405  RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
406  PairFinder< Property::Index, RegisteredPropertyPair>(index) );
407 
408  if ( iter == mRegisteredProperties.end() )
409  {
411  }
412  else
413  {
414  DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
415  }
416 }
417 
418 void TypeInfo::AddAnimatableProperty( const std::string& name, Property::Index index, const Property::Value& defaultValue )
419 {
420  RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
421  PairFinder< Property::Index, RegisteredPropertyPair>(index) );
422 
423  if ( iter == mRegisteredProperties.end() )
424  {
425  mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( defaultValue.GetType(), NULL, NULL, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
426  mPropertyDefaultValues.push_back( PropertyDefaultValuePair( index, defaultValue ) );
427  }
428  else
429  {
430  DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
431  }
432 }
433 
434 void TypeInfo::AddAnimatablePropertyComponent( const std::string& name, Property::Index index, Property::Index baseIndex, unsigned int componentIndex )
435 {
436  Property::Type type = GetPropertyType( baseIndex );
437  DALI_ASSERT_ALWAYS( ( type == Property::VECTOR2 || type == Property::VECTOR3 || type == Property::VECTOR4 ) && "Base property does not support component" );
438 
439  bool success = false;
440 
441  RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
442  PairFinder< Property::Index, RegisteredPropertyPair>(index) );
443 
444  if ( iter == mRegisteredProperties.end() )
445  {
446  iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
447  PropertyComponentFinder< RegisteredPropertyPair >( baseIndex, componentIndex ) );
448 
449  if ( iter == mRegisteredProperties.end() )
450  {
451  mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, NULL, NULL, name, baseIndex, componentIndex ) ) );
452  success = true;
453  }
454  }
455 
456  DALI_ASSERT_ALWAYS( success && "Property component already registered" );
457 }
458 
460 {
461  size_t count( mRegisteredProperties.size() );
462 
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 {
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  {
489  if ( base )
490  {
491  index = GetImplementation(base).GetPropertyIndex( name );
492  }
493  }
494 
495  return index;
496 }
497 
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  {
512  if ( base )
513  {
514  basePropertyIndex = GetImplementation(base).GetBasePropertyIndex( index );
515  }
516  }
517 
518  return basePropertyIndex;
519 }
520 
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  {
535  if ( base )
536  {
537  componentIndex = GetImplementation(base).GetComponentIndex( index );
538  }
539  }
540 
541  return componentIndex;
542 }
543 
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  {
554  {
555  writable = true; // animatable property is writable
556  }
557  else
558  {
559  writable = iter->second.setFunc ? true : false;
560  }
561  }
562  else
563  {
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 
579 {
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  {
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 
606 {
607  PropertyDefaultValueContainer::const_iterator iter = find_if( mPropertyDefaultValues.begin(), mPropertyDefaultValues.end(),
608  PairFinder< Property::Index, PropertyDefaultValuePair >( index ) );
609  if( iter != mPropertyDefaultValues.end() )
610  {
611  return iter->second;
612  }
613  else
614  {
615  return Property::Value( GetPropertyType( index ) );
616  }
617 }
618 
619 void TypeInfo::SetProperty( BaseObject *object, Property::Index index, const Property::Value& value ) const
620 {
621  RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
622  PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
623  if ( iter != mRegisteredProperties.end() )
624  {
625  if( iter->second.setFunc )
626  {
627  iter->second.setFunc( object, index, value );
628  }
629  }
630  else
631  {
633  if ( base )
634  {
635  GetImplementation(base).SetProperty( object, index, value );
636  }
637  else
638  {
639  DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
640  }
641  }
642 }
643 
644 void TypeInfo::SetProperty( BaseObject *object, const std::string& name, const Property::Value& value ) const
645 {
646  RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
647  PropertyNameFinder< RegisteredPropertyPair >( name ) );
648  if ( iter != mRegisteredProperties.end() )
649  {
650  DALI_ASSERT_ALWAYS( iter->second.setFunc && "Trying to write to a read-only property" );
651  iter->second.setFunc( object, iter->first, value );
652  }
653  else
654  {
656  if ( base )
657  {
658  GetImplementation(base).SetProperty( object, name, value );
659  }
660  else
661  {
662  DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
663  }
664  }
665 }
666 
668 {
669  RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
670  PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
671  if( iter != mRegisteredProperties.end() )
672  {
673  // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
674  return iter->second.getFunc( const_cast< BaseObject* >( object ), index );
675  }
676 
678  if ( base )
679  {
680  return GetImplementation( base ).GetProperty( object, index );
681  }
682 
683  DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
684 }
685 
686 Property::Value TypeInfo::GetProperty( const BaseObject *object, const std::string& name ) const
687 {
688  RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
689  PropertyNameFinder< RegisteredPropertyPair >( name ) );
690  if( iter != mRegisteredProperties.end() )
691  {
692  // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
693  return iter->second.getFunc( const_cast< BaseObject* >( object ), iter->first );
694  }
695 
697  if ( base )
698  {
699  return GetImplementation( base ).GetProperty( object, name );
700  }
701 
702  DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
703 }
704 
705 } // namespace Internal
706 
707 } // namespace Dali
Dali Docs Home
Read more about Dali