6d8603e5eaeccbb5b4c9362b72a856936da0f423
[platform/core/uifw/dali-core.git] / dali / internal / event / common / proxy-object.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 // CLASS HEADER
18 #include <dali/internal/event/common/proxy-object.h>
19
20 // EXTERNAL INCLUDES
21 #include <algorithm>
22
23 // INTERNAL INCLUDES
24 #include <dali/public-api/object/property-index.h>
25 #include <dali/integration-api/debug.h>
26 #include <dali/internal/event/common/stage-impl.h>
27 #include <dali/internal/update/common/animatable-property.h>
28 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
29 #include <dali/internal/update/common/property-owner-messages.h>
30 #include <dali/internal/event/animation/active-constraint-base.h>
31 #include <dali/internal/event/animation/constraint-impl.h>
32 #include <dali/internal/event/common/property-notification-impl.h>
33 #include <dali/internal/event/common/property-index-ranges.h>
34 #include <dali/internal/event/common/type-registry-impl.h>
35
36 using Dali::Internal::SceneGraph::AnimatableProperty;
37 using Dali::Internal::SceneGraph::PropertyBase;
38
39 namespace Dali
40 {
41
42 namespace Internal
43 {
44
45 namespace // unnamed namespace
46 {
47 const int SUPPORTED_CAPABILITIES = Dali::Handle::DYNAMIC_PROPERTIES;  // ProxyObject provides this capability
48 typedef Dali::Vector<ProxyObject::Observer*>::Iterator ObserverIter;
49 typedef Dali::Vector<ProxyObject::Observer*>::ConstIterator ConstObserverIter;
50
51 static std::string EMPTY_PROPERTY_NAME;
52
53 #if defined(DEBUG_ENABLED)
54 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_PROXY_OBJECT" );
55 #endif
56 } // unnamed namespace
57
58 const int INVALID_PROPERTY_COMPONENT_INDEX = -1;
59
60 ProxyObject::ProxyObject()
61 : mTypeInfo( NULL ),
62   mNextCustomPropertyIndex( 0u ),
63   mCustomProperties( NULL ),
64   mConstraints( NULL ),
65   mRemovedConstraints( NULL ),
66   mPropertyNotifications( NULL )
67 {
68 }
69
70 void ProxyObject::AddObserver(Observer& observer)
71 {
72   // make sure an observer doesn't observe the same object twice
73   // otherwise it will get multiple calls to OnSceneObjectAdd(), OnSceneObjectRemove() and ProxyDestroyed()
74   DALI_ASSERT_DEBUG( mObservers.End() == std::find( mObservers.Begin(), mObservers.End(), &observer));
75
76   mObservers.PushBack( &observer );
77 }
78
79 void ProxyObject::RemoveObserver(Observer& observer)
80 {
81   // Find the observer...
82   const ConstObserverIter endIter =  mObservers.End();
83   for( ObserverIter iter = mObservers.Begin(); iter != endIter; ++iter)
84   {
85     if( (*iter) == &observer)
86     {
87       mObservers.Erase( iter );
88       break;
89     }
90   }
91   DALI_ASSERT_DEBUG(endIter != mObservers.End());
92 }
93
94 void ProxyObject::OnSceneObjectAdd()
95 {
96   // Notification for observers
97   for( ConstObserverIter iter = mObservers.Begin(),  endIter =  mObservers.End(); iter != endIter; ++iter)
98   {
99     (*iter)->SceneObjectAdded(*this);
100   }
101
102   // enable property notifications in scene graph
103   EnablePropertyNotifications();
104 }
105
106 void ProxyObject::OnSceneObjectRemove()
107 {
108   // Notification for observers
109   for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter )
110   {
111     (*iter)->SceneObjectRemoved(*this);
112   }
113
114   // disable property notifications in scene graph
115   DisablePropertyNotifications();
116 }
117
118 int ProxyObject::GetPropertyComponentIndex( Property::Index index ) const
119 {
120   return INVALID_PROPERTY_COMPONENT_INDEX;
121 }
122
123 bool ProxyObject::Supports( Capability capability ) const
124 {
125   return (capability & SUPPORTED_CAPABILITIES);
126 }
127
128 unsigned int ProxyObject::GetPropertyCount() const
129 {
130   unsigned int count = GetDefaultPropertyCount();
131
132   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Default Properties: %d\n", count );
133
134   TypeInfo* typeInfo( GetTypeInfo() );
135   if ( typeInfo )
136   {
137     unsigned int manual( typeInfo->GetPropertyCount() );
138     count += manual;
139
140     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Manual Properties:  %d\n", manual );
141   }
142
143   if( mCustomProperties )
144   {
145     unsigned int custom( mCustomProperties->size() );
146     count += custom;
147
148     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Custom Properties:  %d\n", custom );
149   }
150
151   DALI_LOG_INFO( gLogFilter, Debug::Concise, "Total Properties:   %d\n", count );
152
153   return count;
154 }
155
156 const std::string& ProxyObject::GetPropertyName( Property::Index index ) const
157 {
158   DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index out of bounds" );
159
160   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
161   {
162     return GetDefaultPropertyName( index );
163   }
164
165   if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
166   {
167     TypeInfo* typeInfo( GetTypeInfo() );
168     if ( typeInfo )
169     {
170       return typeInfo->GetPropertyName( index );
171     }
172     else
173     {
174       DALI_ASSERT_ALWAYS( ! "Property index is invalid" );
175     }
176   }
177
178   if( mCustomProperties )
179   {
180     CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
181     DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Property index is invalid" );
182
183     return entry->second.name;
184   }
185   return EMPTY_PROPERTY_NAME;
186 }
187
188 Property::Index ProxyObject::GetPropertyIndex(const std::string& name) const
189 {
190   Property::Index index = Property::INVALID_INDEX;
191
192   index = GetDefaultPropertyIndex( name );
193
194   if ( index == Property::INVALID_INDEX )
195   {
196     TypeInfo* typeInfo( GetTypeInfo() );
197     if ( typeInfo )
198     {
199       index = typeInfo->GetPropertyIndex( name );
200     }
201   }
202
203   if( index == Property::INVALID_INDEX && mCustomProperties )
204   {
205     // This is slow, but we're not (supposed to be) using property names frequently
206     for ( CustomPropertyLookup::const_iterator iter = mCustomProperties->begin(); mCustomProperties->end() != iter; ++iter )
207     {
208       if (iter->second.name == name)
209       {
210         index = iter->first;
211         break;
212       }
213     }
214   }
215
216   return index;
217 }
218
219 bool ProxyObject::IsPropertyWritable( Property::Index index ) const
220 {
221   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
222
223   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
224   {
225     return IsDefaultPropertyWritable( index );
226   }
227
228   if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
229   {
230     TypeInfo* typeInfo( GetTypeInfo() );
231     if ( typeInfo )
232     {
233       return typeInfo->IsPropertyWritable( index );
234     }
235     else
236     {
237       DALI_ASSERT_ALWAYS( ! "Cannot find property index" );
238     }
239   }
240
241   if( mCustomProperties)
242   {
243     // Check that the index is valid
244     CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
245     DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find property index" );
246
247     return entry->second.IsWritable();
248   }
249   return false;
250 }
251
252 bool ProxyObject::IsPropertyAnimatable( Property::Index index ) const
253 {
254   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
255
256   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
257   {
258     return IsDefaultPropertyAnimatable( index );
259   }
260
261   if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
262   {
263     // Type Registry event-thread only properties are not animatable.
264     return false;
265   }
266
267   if( mCustomProperties )
268   {
269     // Check custom property
270     CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
271     DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find property index" );
272
273     return entry->second.IsAnimatable();
274   }
275   return false;
276 }
277
278 Property::Type ProxyObject::GetPropertyType( Property::Index index ) const
279 {
280   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" );
281
282   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
283   {
284     return GetDefaultPropertyType( index );
285   }
286
287   if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
288   {
289     TypeInfo* typeInfo( GetTypeInfo() );
290     if ( typeInfo )
291     {
292       return typeInfo->GetPropertyType( index );
293     }
294     else
295     {
296       DALI_ASSERT_ALWAYS( ! "Cannot find property index" );
297     }
298   }
299
300   if( mCustomProperties )
301   {
302     CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
303     DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find Property index" );
304
305     return entry->second.type;
306   }
307   return Property::NONE;
308 }
309
310 void ProxyObject::SetProperty( Property::Index index, const Property::Value& propertyValue )
311 {
312   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" );
313
314   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
315   {
316     DALI_ASSERT_ALWAYS( IsDefaultPropertyWritable(index) && "Property is read-only" );
317
318     SetDefaultProperty( index, propertyValue );
319   }
320   else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
321   {
322     TypeInfo* typeInfo( GetTypeInfo() );
323     if ( typeInfo )
324     {
325       typeInfo->SetProperty( this, index, propertyValue );
326     }
327     else
328     {
329       DALI_ASSERT_ALWAYS( ! "Cannot find property index" );
330     }
331   }
332   else if( mCustomProperties )
333   {
334     CustomPropertyLookup::iterator entry = mCustomProperties->find( index );
335     DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find property index" );
336     DALI_ASSERT_ALWAYS( entry->second.IsWritable() && "Property is read-only" );
337
338     // this is only relevant for non animatable properties
339     if(entry->second.IsWritable())
340     {
341       entry->second.value = propertyValue;
342     }
343
344     SetCustomProperty(index, entry->second, propertyValue);
345   }
346 }
347
348 Property::Value ProxyObject::GetProperty(Property::Index index) const
349 {
350   DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index is out of bounds" );
351
352   Property::Value value;
353
354   if ( index < DEFAULT_PROPERTY_MAX_COUNT )
355   {
356     value = GetDefaultProperty( index );
357   }
358   else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
359   {
360     TypeInfo* typeInfo( GetTypeInfo() );
361     if ( typeInfo )
362     {
363       value = typeInfo->GetProperty( this, index );
364     }
365     else
366     {
367       DALI_ASSERT_ALWAYS( ! "Cannot find property index" );
368     }
369   }
370   else if( mCustomProperties )
371   {
372     CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
373     DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find property index" );
374
375     if( !entry->second.IsAnimatable() )
376     {
377       value = entry->second.value;
378     }
379     else
380     {
381       BufferIndex bufferIndex( Stage::GetCurrent()->GetEventBufferIndex() );
382
383       switch ( entry->second.type )
384       {
385         case Property::BOOLEAN:
386         {
387           AnimatableProperty<bool>* property = dynamic_cast< AnimatableProperty<bool>* >( entry->second.GetSceneGraphProperty() );
388           DALI_ASSERT_DEBUG( NULL != property );
389
390           value = (*property)[ bufferIndex ];
391           break;
392         }
393
394         case Property::FLOAT:
395         {
396           AnimatableProperty<float>* property = dynamic_cast< AnimatableProperty<float>* >( entry->second.GetSceneGraphProperty() );
397           DALI_ASSERT_DEBUG( NULL != property );
398
399           value = (*property)[ bufferIndex ];
400           break;
401         }
402
403         case Property::VECTOR2:
404         {
405           AnimatableProperty<Vector2>* property = dynamic_cast< AnimatableProperty<Vector2>* >( entry->second.GetSceneGraphProperty() );
406           DALI_ASSERT_DEBUG( NULL != property );
407
408           value = (*property)[ bufferIndex ];
409           break;
410         }
411
412         case Property::VECTOR3:
413         {
414           AnimatableProperty<Vector3>* property = dynamic_cast< AnimatableProperty<Vector3>* >( entry->second.GetSceneGraphProperty() );
415           DALI_ASSERT_DEBUG( NULL != property );
416
417           value = (*property)[ bufferIndex ];
418           break;
419         }
420
421         case Property::VECTOR4:
422         {
423           AnimatableProperty<Vector4>* property = dynamic_cast< AnimatableProperty<Vector4>* >( entry->second.GetSceneGraphProperty() );
424           DALI_ASSERT_DEBUG( NULL != property );
425
426           value = (*property)[ bufferIndex ];
427           break;
428         }
429
430         case Property::MATRIX:
431         {
432           AnimatableProperty<Matrix>* property = dynamic_cast< AnimatableProperty<Matrix>* >( entry->second.GetSceneGraphProperty() );
433           DALI_ASSERT_DEBUG( NULL != property );
434
435           value = (*property)[ bufferIndex ];
436           break;
437         }
438
439         case Property::MATRIX3:
440         {
441           AnimatableProperty<Matrix3>* property = dynamic_cast< AnimatableProperty<Matrix3>* >( entry->second.GetSceneGraphProperty() );
442           DALI_ASSERT_DEBUG( NULL != property );
443
444           value = (*property)[ bufferIndex ];
445           break;
446         }
447
448         case Property::ROTATION:
449         {
450           AnimatableProperty<Quaternion>* property = dynamic_cast< AnimatableProperty<Quaternion>* >( entry->second.GetSceneGraphProperty() );
451           DALI_ASSERT_DEBUG( NULL != property );
452
453           value = (*property)[ bufferIndex ];
454           break;
455         }
456
457         default:
458         {
459           DALI_ASSERT_ALWAYS( false && "PropertyType enumeration is out of bounds" );
460           break;
461         }
462       } // switch(type)
463     } // if animatable
464
465   } // if custom
466
467   return value;
468 }
469
470 void ProxyObject::GetPropertyIndices( Property::IndexContainer& indices ) const
471 {
472   indices.clear();
473
474   // Default Properties
475   GetDefaultPropertyIndices( indices );
476
477   // Manual Properties
478   TypeInfo* typeInfo( GetTypeInfo() );
479   if ( typeInfo )
480   {
481     typeInfo->GetPropertyIndices( indices );
482   }
483
484   // Custom Properties
485   if ( mCustomProperties )
486   {
487     indices.reserve( indices.size() + mCustomProperties->size() );
488
489     const CustomPropertyLookup::const_iterator endIter = mCustomProperties->end();
490     for ( CustomPropertyLookup::const_iterator iter = mCustomProperties->begin(); iter != endIter; ++iter )
491     {
492       indices.push_back( iter->first );
493     }
494   }
495 }
496
497 Property::Index ProxyObject::RegisterProperty( std::string name, const Property::Value& propertyValue)
498 {
499   // Assert that property name is unused
500   DALI_ASSERT_ALWAYS( Property::INVALID_INDEX == GetPropertyIndex(name) && "Property index is out of bounds" );
501
502   // Create a new property
503   std::auto_ptr<PropertyBase> newProperty;
504
505   switch ( propertyValue.GetType() )
506   {
507     case Property::BOOLEAN:
508     {
509       newProperty.reset(new AnimatableProperty<bool>( propertyValue.Get<bool>()));
510       break;
511     }
512
513     case Property::FLOAT:
514     {
515       newProperty.reset(new AnimatableProperty<float>( propertyValue.Get<float>()));
516       break;
517     }
518
519     case Property::VECTOR2:
520     {
521       newProperty.reset(new AnimatableProperty<Vector2>( propertyValue.Get<Vector2>()));
522       break;
523     }
524
525     case Property::VECTOR3:
526     {
527       newProperty.reset(new AnimatableProperty<Vector3>( propertyValue.Get<Vector3>()));
528       break;
529     }
530
531     case Property::VECTOR4:
532     {
533       newProperty.reset(new AnimatableProperty<Vector4>( propertyValue.Get<Vector4>()));
534       break;
535     }
536
537     case Property::MATRIX:
538     {
539       newProperty.reset(new AnimatableProperty<Matrix>( propertyValue.Get<Matrix>()));
540       break;
541     }
542
543     case Property::MATRIX3:
544     {
545       newProperty.reset(new AnimatableProperty<Matrix3>( propertyValue.Get<Matrix3>()));
546       break;
547     }
548
549     case Property::ROTATION:
550     {
551       newProperty.reset(new AnimatableProperty<Quaternion>( propertyValue.Get<Quaternion>()));
552       break;
553     }
554
555     default:
556     {
557       DALI_LOG_WARNING( "Property Type %d\n", propertyValue.GetType() );
558       DALI_ASSERT_ALWAYS( false && "PropertyType enumeration is out of bounds" );
559       break;
560     }
561   }
562
563   // Default properties start from index zero
564   if ( 0u == mNextCustomPropertyIndex )
565   {
566     mNextCustomPropertyIndex = CUSTOM_PROPERTY_START;
567   }
568
569   // Add entry to the property lookup
570   const Property::Index index = mNextCustomPropertyIndex++;
571
572   CustomPropertyLookup::const_iterator entry = GetCustomPropertyLookup().find( index );
573   DALI_ASSERT_ALWAYS( mCustomProperties->end() == entry && "Custom property already registered" );
574
575   (*mCustomProperties)[ index ] = CustomProperty( name, propertyValue.GetType(), newProperty.get() );
576
577   // The derived class now passes ownership of this new property to a scene-object
578   InstallSceneObjectProperty( *(newProperty.release()), name, index );
579
580   return index;
581 }
582
583 Property::Index ProxyObject::RegisterProperty( std::string name, const Property::Value& propertyValue, Property::AccessMode accessMode)
584 {
585   Property::Index index = Property::INVALID_INDEX;
586
587   if(Property::ANIMATABLE == accessMode)
588   {
589     index = RegisterProperty(name, propertyValue);
590   }
591   else
592   {
593     // Default properties start from index zero
594     if ( 0u == mNextCustomPropertyIndex )
595     {
596       mNextCustomPropertyIndex = CUSTOM_PROPERTY_START;
597     }
598
599     // Add entry to the property lookup
600     index = mNextCustomPropertyIndex++;
601     GetCustomPropertyLookup()[ index ] = CustomProperty( name, propertyValue, accessMode );
602   }
603
604   return index;
605 }
606
607 Dali::PropertyNotification ProxyObject::AddPropertyNotification(Property::Index index,
608                                                                 int componentIndex,
609                                                                 const Dali::PropertyCondition& condition)
610 {
611   if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
612   {
613     if ( index <= PROPERTY_REGISTRATION_MAX_INDEX )
614     {
615       DALI_ASSERT_ALWAYS( false && "Property notification added to non animatable property." );
616     }
617     else if ( mCustomProperties )
618     {
619       CustomPropertyLookup::const_iterator entry = mCustomProperties->find( index );
620       DALI_ASSERT_ALWAYS( mCustomProperties->end() != entry && "Cannot find property index" );
621
622       DALI_ASSERT_ALWAYS( entry->second.IsAnimatable() && "Property notification added to non animatable property (currently not suppported )");
623     }
624   }
625
626   Dali::Handle self(this);
627   Property target( self, index );
628
629   PropertyNotificationPtr internal = PropertyNotification::New( target, componentIndex, condition );
630   Dali::PropertyNotification propertyNotification(internal.Get());
631
632   if( !mPropertyNotifications )
633   {
634     mPropertyNotifications = new PropertyNotificationContainer;
635   }
636   mPropertyNotifications->push_back(propertyNotification);
637
638   return propertyNotification;
639 }
640
641 void ProxyObject::RemovePropertyNotification(Dali::PropertyNotification propertyNotification)
642 {
643   if( mPropertyNotifications )
644   {
645     PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
646     while(iter != mPropertyNotifications->end() )
647     {
648       if(*iter == propertyNotification)
649       {
650         mPropertyNotifications->erase(iter);
651         // As we can't ensure all references are removed, we can just disable
652         // the notification.
653         GetImplementation(propertyNotification).Disable();
654         return;
655       }
656       ++iter;
657     }
658   }
659 }
660
661 void ProxyObject::RemovePropertyNotifications()
662 {
663   if( mPropertyNotifications )
664   {
665     PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
666     while(iter != mPropertyNotifications->end() )
667     {
668       // As we can't ensure all references are removed, we can just disable
669       // the notification.
670       GetImplementation(*iter).Disable();
671       ++iter;
672     }
673
674     mPropertyNotifications->clear();
675   }
676 }
677
678 void ProxyObject::EnablePropertyNotifications()
679 {
680   if( mPropertyNotifications )
681   {
682     PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
683     PropertyNotificationContainerIter endIter = mPropertyNotifications->end();
684
685     for( ; iter != endIter; ++iter )
686     {
687       GetImplementation(*iter).Enable();
688     }
689   }
690 }
691
692 void ProxyObject::DisablePropertyNotifications()
693 {
694   if( mPropertyNotifications )
695   {
696     PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
697     PropertyNotificationContainerIter endIter = mPropertyNotifications->end();
698
699     for( ; iter != endIter; ++iter )
700     {
701       GetImplementation(*iter).Disable();
702     }
703   }
704 }
705
706 Dali::ActiveConstraint ProxyObject::ApplyConstraint( Constraint& constraint )
707 {
708   return Dali::ActiveConstraint(DoApplyConstraint( constraint, NULL/*callback is optional*/ ));
709 }
710
711 Dali::ActiveConstraint ProxyObject::ApplyConstraint( Constraint& constraint, ActiveConstraintCallbackType callback )
712 {
713   return Dali::ActiveConstraint(DoApplyConstraint( constraint, &callback ));
714 }
715
716 ActiveConstraintBase* ProxyObject::DoApplyConstraint( Constraint& constraint, ActiveConstraintCallbackType* callback )
717 {
718   ActiveConstraintBase* activeConstraintImpl = constraint.CreateActiveConstraint();
719   DALI_ASSERT_DEBUG( NULL != activeConstraintImpl );
720
721   Dali::ActiveConstraint activeConstraint( activeConstraintImpl );
722
723   if( !mConstraints )
724   {
725     mConstraints = new ActiveConstraintContainer;
726   }
727   mConstraints->push_back( activeConstraint );
728
729   activeConstraintImpl->FirstApply( *this, constraint.GetApplyTime(), callback );
730
731   return activeConstraintImpl;
732 }
733
734 void ProxyObject::DeleteRemovedConstraints()
735 {
736   if( ! mRemovedConstraints )
737   {
738     return;
739   }
740
741   // Discard constraints which are fully removed
742   for ( ActiveConstraintIter iter = mRemovedConstraints->begin(); mRemovedConstraints->end() != iter ;)
743   {
744     if ( !( GetImplementation( *iter ).IsRemoving() ) )
745     {
746       iter = mRemovedConstraints->erase( iter );
747     }
748     else
749     {
750       ++iter;
751     }
752   }
753 }
754
755 void ProxyObject::SetCustomProperty( Property::Index index, const CustomProperty& entry, const Property::Value& value )
756 {
757   switch ( entry.type )
758   {
759     case Property::BOOLEAN:
760     {
761       AnimatableProperty<bool>* property = dynamic_cast< AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
762       DALI_ASSERT_DEBUG( NULL != property );
763
764       // property is being used in a separate thread; queue a message to set the property
765       BakeMessage<bool>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<bool>() );
766       break;
767     }
768
769     case Property::FLOAT:
770     {
771       AnimatableProperty<float>* property = dynamic_cast< AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
772       DALI_ASSERT_DEBUG( NULL != property );
773
774       // property is being used in a separate thread; queue a message to set the property
775       BakeMessage<float>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<float>() );
776       break;
777     }
778
779     case Property::VECTOR2:
780     {
781       AnimatableProperty<Vector2>* property = dynamic_cast< AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
782       DALI_ASSERT_DEBUG( NULL != property );
783
784       // property is being used in a separate thread; queue a message to set the property
785       BakeMessage<Vector2>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Vector2>() );
786       break;
787     }
788
789     case Property::VECTOR3:
790     {
791       AnimatableProperty<Vector3>* property = dynamic_cast< AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
792       DALI_ASSERT_DEBUG( NULL != property );
793
794       // property is being used in a separate thread; queue a message to set the property
795       BakeMessage<Vector3>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Vector3>() );
796       break;
797     }
798
799     case Property::VECTOR4:
800     {
801       AnimatableProperty<Vector4>* property = dynamic_cast< AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
802       DALI_ASSERT_DEBUG( NULL != property );
803
804       // property is being used in a separate thread; queue a message to set the property
805       BakeMessage<Vector4>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Vector4>() );
806       break;
807     }
808
809     case Property::ROTATION:
810     {
811       AnimatableProperty<Quaternion>* property = dynamic_cast< AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
812       DALI_ASSERT_DEBUG( NULL != property );
813
814       // property is being used in a separate thread; queue a message to set the property
815       BakeMessage<Quaternion>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Quaternion>() );
816       break;
817     }
818
819     case Property::MATRIX:
820     {
821       AnimatableProperty<Matrix>* property = dynamic_cast< AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
822       DALI_ASSERT_DEBUG( NULL != property );
823
824       // property is being used in a separate thread; queue a message to set the property
825       BakeMessage<Matrix>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Matrix>() );
826       break;
827     }
828
829     case Property::MATRIX3:
830     {
831       AnimatableProperty<Matrix3>* property = dynamic_cast< AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
832       DALI_ASSERT_DEBUG( NULL != property );
833
834       // property is being used in a separate thread; queue a message to set the property
835       BakeMessage<Matrix3>( Stage::GetCurrent()->GetUpdateInterface(), *property, value.Get<Matrix3>() );
836       break;
837     }
838
839     default:
840     {
841       DALI_ASSERT_ALWAYS(false && "Property type enumeration out of bounds"); // should not come here
842       break;
843     }
844   }
845 }
846
847 CustomPropertyLookup& ProxyObject::GetCustomPropertyLookup() const
848 {
849   // lazy create
850   if( !mCustomProperties )
851   {
852     mCustomProperties = new CustomPropertyLookup;
853   }
854   return *mCustomProperties;
855 }
856
857 TypeInfo* ProxyObject::GetTypeInfo() const
858 {
859   if ( !mTypeInfo )
860   {
861     // This uses a dynamic_cast so can be quite expensive so we only really want to do it once
862     // especially as the type-info does not change during the life-time of an application
863
864     Dali::TypeInfo typeInfoHandle = TypeRegistry::Get()->GetTypeInfo( this );
865     if ( typeInfoHandle )
866     {
867       mTypeInfo = &GetImplementation( typeInfoHandle );
868     }
869   }
870
871   return mTypeInfo;
872 }
873
874 void ProxyObject::RemoveConstraint( Dali::ActiveConstraint activeConstraint )
875 {
876   if( mConstraints )
877   {
878     // If we have nothing in the scene-graph, just remove the activeConstraint from container
879     const SceneGraph::PropertyOwner* propertyOwner = GetSceneObject();
880     if ( NULL == propertyOwner )
881     {
882       ActiveConstraintIter it( std::find( mConstraints->begin(), mConstraints->end(), activeConstraint ) );
883       if( it != mConstraints->end() )
884       {
885         mConstraints->erase( it );
886       }
887       delete mRemovedConstraints;
888       mRemovedConstraints = NULL;
889       return;
890     }
891
892     // Discard constraints which are fully removed
893     DeleteRemovedConstraints();
894
895     ActiveConstraintIter it( std::find( mConstraints->begin(), mConstraints->end(), activeConstraint ) );
896     if( it != mConstraints->end() )
897     {
898       ActiveConstraintBase& constraint = GetImplementation( *it );
899
900       constraint.BeginRemove();
901       mConstraints->erase( it );
902
903       if ( constraint.IsRemoving() )
904       {
905         if( !mRemovedConstraints )
906         {
907           mRemovedConstraints = new ActiveConstraintContainer;
908         }
909         // Wait for remove animation before destroying active-constraints
910         mRemovedConstraints->push_back( *it );
911       }
912     }
913   }
914 }
915
916 void ProxyObject::RemoveConstraints()
917 {
918   if( mConstraints )
919   {
920     // If we have nothing in the scene-graph, just clear constraint containers
921     const SceneGraph::PropertyOwner* propertyOwner = GetSceneObject();
922     if ( NULL == propertyOwner )
923     {
924       delete mConstraints;
925       mConstraints = NULL;
926       delete mRemovedConstraints;
927       mRemovedConstraints = NULL;
928       return;
929     }
930
931     // Discard constraints which are fully removed
932     DeleteRemovedConstraints();
933
934     const ActiveConstraintConstIter endIter = mConstraints->end();
935     for ( ActiveConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter )
936     {
937       ActiveConstraintBase& constraint = GetImplementation( *iter );
938
939       constraint.BeginRemove();
940
941       if ( constraint.IsRemoving() )
942       {
943         if( !mRemovedConstraints )
944         {
945           mRemovedConstraints = new ActiveConstraintContainer;
946         }
947         // Wait for remove animation before destroying active-constraints
948         mRemovedConstraints->push_back( *iter );
949       }
950     }
951
952     delete mConstraints;
953     mConstraints = NULL;
954   }
955 }
956
957 ProxyObject::~ProxyObject()
958 {
959   // Notification for observers
960   for( ConstObserverIter iter = mObservers.Begin(), endIter =  mObservers.End(); iter != endIter; ++iter)
961   {
962     (*iter)->ProxyDestroyed(*this);
963   }
964
965   delete mCustomProperties;
966   delete mConstraints;
967   delete mRemovedConstraints;
968   delete mPropertyNotifications;
969 }
970
971 } // namespace Internal
972
973 } // namespace Dali