c9f04eb6d0b9fc3b2f41cfc72b27689e1eec539a
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / constraint-base.cpp
1 /*
2  * Copyright (c) 2018 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\n" );
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       if( mTargetObject && mSceneGraphConstraint )
110       {
111         const SceneGraph::PropertyOwner& propertyOwner =  mTargetObject->GetSceneObject();
112         // Remove from scene-graph
113         RemoveConstraintMessage( GetEventThreadServices(), propertyOwner, *(mSceneGraphConstraint) );
114         // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
115         mSceneGraphConstraint = NULL;
116       }
117     }
118   }
119 }
120
121 Object* ConstraintBase::GetParent()
122 {
123   return mTargetObject;
124 }
125
126 Dali::Handle ConstraintBase::GetTargetObject()
127 {
128   return Dali::Handle( mTargetObject );
129 }
130
131 Property::Index ConstraintBase::GetTargetProperty()
132 {
133   return mTargetPropertyIndex;
134 }
135
136 void ConstraintBase::SetRemoveAction( ConstraintBase::RemoveAction action )
137 {
138   mRemoveAction = action;
139 }
140
141 ConstraintBase::RemoveAction ConstraintBase::GetRemoveAction() const
142 {
143   return mRemoveAction;
144 }
145
146 void ConstraintBase::SetTag( uint32_t tag )
147 {
148   mTag = tag;
149 }
150
151 uint32_t ConstraintBase::GetTag() const
152 {
153   return mTag;
154 }
155
156 void ConstraintBase::SceneObjectAdded( Object& object )
157 {
158   if ( mApplied &&
159        ( NULL == mSceneGraphConstraint ) &&
160        mTargetObject )
161   {
162     ConnectConstraint();
163   }
164 }
165
166 void ConstraintBase::SceneObjectRemoved( Object& object )
167 {
168   if ( mSceneGraphConstraint )
169   {
170     // An input property owning source has been deleted, need to tell the scene-graph-constraint owner to remove it
171     if ( &object != mTargetObject )
172     {
173       if( mTargetObject )
174       {
175         const SceneGraph::PropertyOwner& propertyOwner = mTargetObject->GetSceneObject();
176         // Remove from scene-graph
177         RemoveConstraintMessage( GetEventThreadServices(), propertyOwner, *(mSceneGraphConstraint) );
178       }
179     }
180
181     // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
182     mSceneGraphConstraint = NULL;
183   }
184 }
185
186 void ConstraintBase::ObjectDestroyed( Object& object )
187 {
188   // Remove object pointer from observation set
189   ObjectIter iter = std::find( mObservedObjects.Begin(), mObservedObjects.End(), &object );
190   DALI_ASSERT_DEBUG( mObservedObjects.End() != iter );
191   mObservedObjects.Erase( iter );
192
193   // Constraint is not useful anymore as an input-source has been destroyed
194   mSourceDestroyed = true;
195
196   // Stop observing the remaining objects
197   StopObservation();
198
199   // Clear our sources as well
200   mSources.clear();
201
202   // Discard all object & scene-graph pointers
203   mSceneGraphConstraint = NULL;
204   mTargetObject = NULL;
205 }
206
207 void ConstraintBase::ObserveObject( Object& object )
208 {
209   ObjectIter iter = std::find( mObservedObjects.Begin(), mObservedObjects.End(), &object );
210   if ( mObservedObjects.End() == iter )
211   {
212     object.AddObserver( *this );
213     mObservedObjects.PushBack( &object );
214   }
215 }
216
217 void ConstraintBase::StopObservation()
218 {
219   const ObjectIter end = mObservedObjects.End();
220   for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter )
221   {
222     (*iter)->RemoveObserver( *this );
223   }
224
225   mObservedObjects.Clear();
226 }
227
228 } // namespace Internal
229
230 } // namespace Dali