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