Merge remote-tracking branch 'origin/tizen' into new_text
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / constraint-base.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/animation/constraint-base.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/object/handle.h>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/internal/event/common/event-thread-services.h>
25 #include <dali/internal/event/common/property-helper.h>
26 #include <dali/internal/event/common/stage-impl.h>
27 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
28 #include <dali/internal/update/common/animatable-property.h>
29 #include <dali/internal/update/common/property-owner-messages.h>
30
31 using Dali::Internal::SceneGraph::AnimatableProperty;
32
33 namespace Dali
34 {
35
36 namespace Internal
37 {
38
39 ConstraintBase::ConstraintBase( Object& object, Property::Index targetPropertyIndex, SourceContainer& sources )
40 : mEventThreadServices( *Stage::GetCurrent() ),
41   mTargetObject( &object ),
42   mSceneGraphConstraint( NULL ),
43   mSources( sources ),
44   mObservedObjects(),
45   mTargetPropertyIndex( targetPropertyIndex ),
46   mRemoveAction( Dali::Constraint::DEFAULT_REMOVE_ACTION ),
47   mTag( 0 ),
48   mApplied( false ),
49   mSourceDestroyed( false )
50 {
51   ObserveObject( object );
52 }
53
54 ConstraintBase::~ConstraintBase()
55 {
56   StopObservation();
57
58   RemoveInternal();
59 }
60
61 void ConstraintBase::AddSource( Source source )
62 {
63   mSources.push_back( source );
64
65   // Observe the object providing this property
66   if ( OBJECT_PROPERTY == source.sourceType )
67   {
68     if ( source.object != NULL )
69     {
70       ObserveObject( *source.object );
71     }
72     else
73     {
74       DALI_LOG_ERROR( "Constraint source object not found" );
75     }
76   }
77 }
78
79 void ConstraintBase::Apply()
80 {
81   if ( mTargetObject && !mApplied && !mSourceDestroyed )
82   {
83     mApplied = true;
84     ConnectConstraint();
85
86     mTargetObject->ApplyConstraint( *this );
87   }
88 }
89
90 void ConstraintBase::Remove()
91 {
92   RemoveInternal();
93
94   if( mTargetObject )
95   {
96     mTargetObject->RemoveConstraint( *this );
97   }
98 }
99
100 void ConstraintBase::RemoveInternal()
101 {
102   if ( mApplied )
103   {
104     mApplied = false;
105
106     // Guard against constraint sending messages during core destruction
107     if( Stage::IsInstalled() )
108     {
109       const SceneGraph::PropertyOwner* propertyOwner = mTargetObject ? mTargetObject->GetSceneObject() : NULL;
110
111       if ( propertyOwner &&
112            mSceneGraphConstraint )
113       {
114         // Remove from scene-graph
115         RemoveConstraintMessage( GetEventThreadServices(), *propertyOwner, *(mSceneGraphConstraint) );
116
117         // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
118         mSceneGraphConstraint = NULL;
119       }
120     }
121   }
122 }
123
124 Object* ConstraintBase::GetParent()
125 {
126   return mTargetObject;
127 }
128
129 Dali::Handle ConstraintBase::GetTargetObject()
130 {
131   return Dali::Handle( mTargetObject );
132 }
133
134 Property::Index ConstraintBase::GetTargetProperty()
135 {
136   return mTargetPropertyIndex;
137 }
138
139 void ConstraintBase::SetRemoveAction( ConstraintBase::RemoveAction action )
140 {
141   mRemoveAction = action;
142 }
143
144 ConstraintBase::RemoveAction ConstraintBase::GetRemoveAction() const
145 {
146   return mRemoveAction;
147 }
148
149 void ConstraintBase::SetTag(const unsigned int tag)
150 {
151   mTag = tag;
152 }
153
154 unsigned int ConstraintBase::GetTag() const
155 {
156   return mTag;
157 }
158
159 void ConstraintBase::SceneObjectAdded( Object& object )
160 {
161   if ( mApplied &&
162        ( NULL == mSceneGraphConstraint ) &&
163        mTargetObject )
164   {
165     ConnectConstraint();
166   }
167 }
168
169 void ConstraintBase::SceneObjectRemoved( Object& object )
170 {
171   if ( mSceneGraphConstraint )
172   {
173     // An input property owning source has been deleted, need to tell the scene-graph-constraint owner to remove it
174     if ( &object != mTargetObject )
175     {
176       const SceneGraph::PropertyOwner* propertyOwner = mTargetObject ? mTargetObject->GetSceneObject() : NULL;
177
178       if( propertyOwner )
179       {
180         // Remove from scene-graph
181         RemoveConstraintMessage( GetEventThreadServices(), *propertyOwner, *(mSceneGraphConstraint) );
182       }
183     }
184
185     // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
186     mSceneGraphConstraint = NULL;
187   }
188 }
189
190 void ConstraintBase::ObjectDestroyed( Object& object )
191 {
192   // Remove object pointer from observation set
193   ObjectIter iter = std::find( mObservedObjects.Begin(), mObservedObjects.End(), &object );
194   DALI_ASSERT_DEBUG( mObservedObjects.End() != iter );
195   mObservedObjects.Erase( iter );
196
197   if ( &object != mTargetObject )
198   {
199     // Constraint is not useful anymore as an input-source has been destroyed
200     mSourceDestroyed = true;
201
202     // Stop observing the remaining objects
203     StopObservation();
204
205     // Clear our sources as well
206     mSources.clear();
207
208     // We should remove ourselves from the target-object's constraints as well
209     if ( mTargetObject )
210     {
211       mTargetObject->RemoveConstraint( *this );
212     }
213   }
214
215   // NOTE: We do not clear our sources if our target-object is destroyed because we may want to clone this constraint for another target
216
217   // Discard all object & scene-graph pointers
218   mSceneGraphConstraint = NULL;
219   mTargetObject = NULL;
220 }
221
222 void ConstraintBase::ObserveObject( Object& object )
223 {
224   ObjectIter iter = std::find( mObservedObjects.Begin(), mObservedObjects.End(), &object );
225   if ( mObservedObjects.End() == iter )
226   {
227     object.AddObserver( *this );
228     mObservedObjects.PushBack( &object );
229   }
230 }
231
232 void ConstraintBase::StopObservation()
233 {
234   const ObjectIter end = mObservedObjects.End();
235   for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter )
236   {
237     (*iter)->RemoveObserver( *this );
238   }
239
240   mObservedObjects.Clear();
241 }
242
243 } // namespace Internal
244
245 } // namespace Dali