ab1260e4fc2ac96250a3589bbe20e46a687cc4d4
[platform/core/uifw/dali-core.git] / dali / internal / event / common / property-notification-impl.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/common/property-notification-impl.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/common/dali-common.h>
23 #include <dali/public-api/math/vector2.h>
24 #include <dali/public-api/math/radian.h>
25 #include <dali/public-api/actors/actor.h>
26 #include <dali/internal/event/actors/actor-impl.h>
27 #include <dali/internal/event/common/property-notification-manager.h>
28 #include <dali/internal/event/common/object-impl.h>
29 #include <dali/internal/event/common/stage-impl.h>
30 #include <dali/internal/update/manager/update-manager.h>
31 #include <dali/internal/update/common/scene-graph-property-notification.h>
32 #include <dali/internal/event/common/thread-local-storage.h>
33
34 using Dali::Internal::SceneGraph::UpdateManager;
35
36 namespace Dali
37 {
38
39 namespace Internal
40 {
41
42 PropertyNotificationPtr PropertyNotification::New(Property& target,
43                                                   int componentIndex,
44                                                   const Dali::PropertyCondition& condition)
45 {
46   ThreadLocalStorage& tls = ThreadLocalStorage::Get();
47
48   UpdateManager& updateManager = tls.GetUpdateManager();
49
50   PropertyNotificationManager& propertyNotificationManager = tls.GetPropertyNotificationManager();
51   PropertyNotificationPtr propertyNotification = new PropertyNotification(updateManager,
52                                                                           propertyNotificationManager,
53                                                                           target,
54                                                                           componentIndex,
55                                                                           condition);
56   return propertyNotification;
57 }
58
59 PropertyNotification::PropertyNotification( UpdateManager& updateManager,
60                                             PropertyNotificationManager& propertyNotificationManager,
61                                             Property& target,
62                                             int componentIndex,
63                                             const Dali::PropertyCondition& condition )
64 : mUpdateManager( updateManager ),
65   mPropertyNotification( NULL ),
66   mPropertyNotificationManager( propertyNotificationManager ),
67   mObjectPropertyIndex( target.propertyIndex ),
68   mPropertyType( Property::NONE ),
69   mComponentIndex( componentIndex ),
70   mCondition( condition ),
71   mNotifyMode( Dali::PropertyNotification::NotifyOnTrue ),
72   mNotifyResult( false ),
73   mCompare( false )
74 {
75   const Internal::PropertyCondition& conditionImpl = GetImplementation( condition );
76
77   Dali::Vector<float>::SizeType count = conditionImpl.arguments.Count();
78   for( Dali::Vector<float>::SizeType index = 0; index < count; ++index )
79   {
80     mRawConditionArgs.PushBack( conditionImpl.arguments[ index ] );
81   }
82
83   // Observe target object and create/destroy notification scene object accordingly.
84   mObject = dynamic_cast<Object*>( &GetImplementation(target.object) );
85   if ( mObject )
86   {
87     mPropertyType = mObject->GetPropertyType(mObjectPropertyIndex);
88
89     int internalComponentIndex = mObject->GetPropertyComponentIndex(mObjectPropertyIndex);
90     if( internalComponentIndex != Property::INVALID_COMPONENT_INDEX )
91     {
92       // override the one passed in
93       mComponentIndex = internalComponentIndex;
94     }
95     if(mComponentIndex != Property::INVALID_COMPONENT_INDEX)
96     {
97       Property::Type type = mObject->GetPropertyType(mObjectPropertyIndex);
98       if( type == Property::VECTOR2
99           || type == Property::VECTOR3
100           || type == Property::VECTOR4 )
101       {
102         mPropertyType = Property::FLOAT;
103       }
104     }
105
106   // In Size Property case, swapping components occurs sometimes.
107   // To cover swapping components, previous and current components should be compared.
108   if( mObjectPropertyIndex == Dali::Actor::Property::SIZE
109       && mObject->GetPropertyType(mObjectPropertyIndex) == Property::VECTOR3 )
110   {
111     mCompare = true;
112     for( int i = 0; i < 3; ++i )
113     {
114       mRawConditionArgs.PushBack( 0.0f );
115     }
116   }
117
118     // all objects always have scene object
119     CreateSceneObject();
120   }
121
122   // Connect to the property notification manager
123   mPropertyNotificationManager.PropertyNotificationCreated( *this );
124 }
125
126 PropertyNotification::~PropertyNotification()
127 {
128   Disable();
129
130   // Guard to disallow use of PropertyNotificationManager after Core has been destroyed
131   if ( Stage::IsInstalled() )
132   {
133     // Disconnect from the property notification manager
134     mPropertyNotificationManager.PropertyNotificationDestroyed( *this );
135   }
136 }
137
138 Dali::PropertyNotifySignalType& PropertyNotification::NotifySignal()
139 {
140   return mNotifySignal;
141 }
142
143 void PropertyNotification::EmitSignalNotify()
144 {
145   Dali::PropertyNotification source(this);
146
147   mNotifySignal.Emit( source );
148 }
149
150 void PropertyNotification::Enable()
151 {
152   CreateSceneObject();
153 }
154
155 void PropertyNotification::Disable()
156 {
157   // Guard to allow handle destruction after Core has been destroyed
158   if ( Stage::IsInstalled() )
159   {
160     // Stop scene-graph from monitoring the target's properties.
161     DestroySceneObject();
162   }
163 }
164
165 void PropertyNotification::SetNotifyResult( bool result )
166 {
167   mNotifyResult = result;
168 }
169
170 const Dali::PropertyCondition& PropertyNotification::GetCondition() const
171 {
172   return mCondition;
173 }
174
175 Dali::Handle PropertyNotification::GetTarget() const
176 {
177   Dali::Handle handle(mObject);
178
179   return handle;
180 }
181
182 Property::Index PropertyNotification::GetTargetProperty() const
183 {
184   return mObjectPropertyIndex;
185 }
186
187 void PropertyNotification::SetNotifyMode( NotifyMode mode )
188 {
189   mNotifyMode = mode;
190   if( mPropertyNotification )
191   {
192     PropertyNotificationSetNotifyModeMessage( mUpdateManager, mPropertyNotification, mode );
193   }
194 }
195
196 PropertyNotification::NotifyMode PropertyNotification::GetNotifyMode()
197 {
198   return mNotifyMode;
199 }
200
201 bool PropertyNotification::GetNotifyResult() const
202 {
203   return mNotifyResult;
204 }
205
206 bool PropertyNotification::CompareSceneObject( const SceneGraph::PropertyNotification* sceneObject )
207 {
208   return sceneObject && sceneObject == mPropertyNotification;
209 }
210
211 void PropertyNotification::CreateSceneObject()
212 {
213   // this method can be called from constructor and on stage connection
214   if( !mPropertyNotification )
215   {
216     // Create a new PropertyNotification, keep a const pointer to it
217     mPropertyNotification = SceneGraph::PropertyNotification::New( *mObject,
218                                                                    mObjectPropertyIndex,
219                                                                    mPropertyType,
220                                                                    mComponentIndex,
221                                                                    GetImplementation( mCondition ).type,
222                                                                    mRawConditionArgs,
223                                                                    mNotifyMode,
224                                                                    mCompare );
225     OwnerPointer< SceneGraph::PropertyNotification > transferOwnership( const_cast<SceneGraph::PropertyNotification*>( mPropertyNotification ) );
226     AddPropertyNotificationMessage( mUpdateManager, transferOwnership );
227   }
228 }
229
230 void PropertyNotification::DestroySceneObject()
231 {
232   if ( mPropertyNotification != NULL )
233   {
234     // Remove PropertyNotification using a message to the update manager
235     RemovePropertyNotificationMessage( mUpdateManager, *mPropertyNotification );
236     mPropertyNotification = NULL;
237   }
238 }
239
240 } // namespace Internal
241
242 } // namespace Dali