Refactor SceneGraphProperty handling code in event side to make RegisterProperty...
[platform/core/uifw/dali-core.git] / dali / internal / event / events / pan-gesture-detector-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/events/pan-gesture-detector-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <cstring> // for strcmp
23
24 // INTERNAL INCLUDES
25 #include <dali/public-api/events/pan-gesture.h>
26 #include <dali/public-api/object/type-registry.h>
27 #include <dali/public-api/math/radian.h>
28 #include <dali/public-api/math/degree.h>
29 #include <dali/integration-api/debug.h>
30 #include <dali/internal/event/actors/actor-impl.h>
31 #include <dali/internal/event/common/property-helper.h>
32 #include <dali/internal/event/common/thread-local-storage.h>
33 #include <dali/internal/event/events/gesture-event-processor.h>
34 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
35
36 namespace Dali
37 {
38
39 namespace Internal
40 {
41
42 namespace
43 {
44
45 // Properties
46
47 //              Name                  Type   writable animatable constraint-input  enum for index-checking
48 DALI_PROPERTY_TABLE_BEGIN
49 DALI_PROPERTY( "screenPosition",      VECTOR2, false, false, true,   Dali::PanGestureDetector::Property::SCREEN_POSITION     )
50 DALI_PROPERTY( "screenDisplacement",  VECTOR2, false, false, true,   Dali::PanGestureDetector::Property::SCREEN_DISPLACEMENT )
51 DALI_PROPERTY( "screenVelocity",      VECTOR2, false, false, true,   Dali::PanGestureDetector::Property::SCREEN_VELOCITY     )
52 DALI_PROPERTY( "localPosition",       VECTOR2, false, false, true,   Dali::PanGestureDetector::Property::LOCAL_POSITION      )
53 DALI_PROPERTY( "localDisplacement",   VECTOR2, false, false, true,   Dali::PanGestureDetector::Property::LOCAL_DISPLACEMENT  )
54 DALI_PROPERTY( "localVelocity",       VECTOR2, false, false, true,   Dali::PanGestureDetector::Property::LOCAL_VELOCITY      )
55 DALI_PROPERTY( "panning",             BOOLEAN, false, false, true,   Dali::PanGestureDetector::Property::PANNING             )
56 DALI_PROPERTY_TABLE_END( DEFAULT_GESTURE_DETECTOR_PROPERTY_START_INDEX, PanGestureDetectorDefaultProperties )
57
58 // Signals
59
60 const char* const SIGNAL_PAN_DETECTED = "panDetected";
61
62 BaseHandle Create()
63 {
64   return Dali::PanGestureDetector::New();
65 }
66
67 TypeRegistration mType( typeid(Dali::PanGestureDetector), typeid(Dali::GestureDetector), Create, PanGestureDetectorDefaultProperties );
68
69 SignalConnectorType signalConnector1( mType, SIGNAL_PAN_DETECTED, &PanGestureDetector::DoConnectSignal );
70
71 #if defined(DEBUG_ENABLED)
72 Integration::Log::Filter* gLogFilter  = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_PAN_GESTURE_DETECTOR");
73 #endif
74
75 /**
76  * Returns the angle going in the opposite direction to that specified by angle.
77  */
78 float GetOppositeAngle( float angle )
79 {
80   // Calculate the opposite angle so that we cover both directions.
81   if ( angle <= 0.0f )
82   {
83     angle += Math::PI;
84   }
85   else
86   {
87     angle -= Math::PI;
88   }
89
90   return angle;
91 }
92
93 } // unnamed namespace
94
95 PanGestureDetectorPtr PanGestureDetector::New()
96 {
97   const SceneGraph::PanGesture& sceneObject = ThreadLocalStorage::Get().GetGestureEventProcessor().GetPanGestureProcessor().GetSceneObject();
98   return new PanGestureDetector( sceneObject );
99 }
100
101 void PanGestureDetector::SetMinimumTouchesRequired(unsigned int minimum)
102 {
103   DALI_ASSERT_ALWAYS( minimum > 0 && "Can only set a positive number of required touches" );
104
105   if (mMinimumTouches != minimum)
106   {
107     DALI_LOG_INFO( gLogFilter, Debug::Concise, "Minimum Touches Set: %d\n", minimum );
108
109     mMinimumTouches = minimum;
110
111     if (!mAttachedActors.empty())
112     {
113       DALI_LOG_INFO( gLogFilter, Debug::General, "Updating Gesture Detector\n");
114
115       mGestureEventProcessor.GestureDetectorUpdated(this);
116     }
117   }
118 }
119
120 void PanGestureDetector::SetMaximumTouchesRequired(unsigned int maximum)
121 {
122   DALI_ASSERT_ALWAYS( maximum > 0 && "Can only set a positive number of maximum touches" );
123
124   if (mMaximumTouches != maximum)
125   {
126     DALI_LOG_INFO( gLogFilter, Debug::Concise, "Maximum Touches Set: %d\n", maximum );
127
128     mMaximumTouches = maximum;
129
130     if (!mAttachedActors.empty())
131     {
132       DALI_LOG_INFO( gLogFilter, Debug::General, "Updating Gesture Detector\n");
133
134       mGestureEventProcessor.GestureDetectorUpdated(this);
135     }
136   }
137 }
138
139 unsigned int PanGestureDetector::GetMinimumTouchesRequired() const
140 {
141   return mMinimumTouches;
142 }
143
144 unsigned int PanGestureDetector::GetMaximumTouchesRequired() const
145 {
146   return mMaximumTouches;
147 }
148
149 void PanGestureDetector::AddAngle( Radian angle, Radian threshold )
150 {
151   threshold = fabsf( threshold ); // Ensure the threshold is positive.
152
153   // If the threshold is greater than PI, then just use PI
154   // This means that any panned angle will invoke the pan gesture. We should still add this angle as
155   // an angle may have been added previously with a small threshold.
156   if ( threshold > Math::PI )
157   {
158     threshold = Math::PI;
159   }
160
161   angle = WrapInDomain( angle, -Math::PI, Math::PI );
162
163   DALI_LOG_INFO( gLogFilter, Debug::Concise, "Angle Added: %.2f, Threshold: %.2f\n", Degree(angle), Degree(threshold) );
164
165   AngleThresholdPair pair( angle, threshold );
166   mAngleContainer.push_back( pair );
167 }
168
169 void PanGestureDetector::AddDirection( Radian direction, Radian threshold )
170 {
171   AddAngle( direction, threshold );
172
173   // Calculate the opposite angle so that we cover the entire direction.
174   direction = GetOppositeAngle( direction );
175
176   AddAngle( direction, threshold );
177 }
178
179 size_t PanGestureDetector::GetAngleCount() const
180 {
181   return mAngleContainer.size();
182 }
183
184 PanGestureDetector::AngleThresholdPair PanGestureDetector::GetAngle(size_t index) const
185 {
186   PanGestureDetector::AngleThresholdPair ret( Radian(0),Radian(0) );
187
188   if( index < mAngleContainer.size() )
189   {
190     ret = mAngleContainer[index];
191   }
192
193   return ret;
194 }
195
196
197 void PanGestureDetector::ClearAngles()
198 {
199   mAngleContainer.clear();
200 }
201
202 void PanGestureDetector::RemoveAngle( Radian angle )
203 {
204   angle = WrapInDomain( angle, -Math::PI, Math::PI );
205
206   for (AngleContainer::iterator iter = mAngleContainer.begin(), endIter = mAngleContainer.end(); iter != endIter; ++iter )
207   {
208     if ( iter->first == angle )
209     {
210       mAngleContainer.erase( iter );
211       break;
212     }
213   }
214 }
215
216 void PanGestureDetector::RemoveDirection( Radian direction )
217 {
218   RemoveAngle( direction );
219
220   // Calculate the opposite angle so that we cover the entire direction.
221   direction = GetOppositeAngle( direction );
222
223   RemoveAngle( direction );
224 }
225
226 bool PanGestureDetector::RequiresDirectionalPan() const
227 {
228   // If no directional angles have been added to the container then we do not require directional panning
229   return !mAngleContainer.empty();
230 }
231
232 bool PanGestureDetector::CheckAngleAllowed( Radian angle ) const
233 {
234   bool allowed( false );
235   if ( mAngleContainer.empty() )
236   {
237     allowed = true;
238   }
239   else
240   {
241     for ( AngleContainer::const_iterator iter = mAngleContainer.begin(), endIter = mAngleContainer.end(); iter != endIter; ++iter )
242     {
243       float angleAllowed( iter->first );
244       float threshold ( iter->second );
245
246       DALI_LOG_INFO( gLogFilter, Debug::General,
247                      "AngleToCheck: %.2f, CompareWith: %.2f, Threshold: %.2f\n",
248                      Degree(angle), Degree(angleAllowed), Degree(threshold) );
249
250       float relativeAngle( fabsf( WrapInDomain( angle - angleAllowed, -Math::PI, Math::PI ) ) );
251       if ( relativeAngle <= threshold )
252       {
253         allowed = true;
254         break;
255       }
256     }
257   }
258
259   return allowed;
260 }
261
262 void PanGestureDetector::EmitPanGestureSignal(Dali::Actor actor, const PanGesture& pan)
263 {
264   if ( !mDetectedSignal.Empty() )
265   {
266     // Guard against destruction during signal emission
267     Dali::PanGestureDetector handle( this );
268
269     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Emitting Signal (%p)\n", this );
270
271     mDetectedSignal.Emit( actor, pan );
272   }
273 }
274
275 bool PanGestureDetector::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
276 {
277   bool connected( true );
278   PanGestureDetector* gesture = static_cast< PanGestureDetector* >(object); // TypeRegistry guarantees that this is the correct type.
279
280   if ( 0 == strcmp( signalName.c_str(), SIGNAL_PAN_DETECTED ) )
281   {
282     gesture->DetectedSignal().Connect( tracker, functor );
283   }
284   else
285   {
286     // signalName does not match any signal
287     connected = false;
288   }
289
290   return connected;
291 }
292
293 void PanGestureDetector::SetPanGestureProperties( const PanGesture& pan )
294 {
295   ThreadLocalStorage::Get().GetGestureEventProcessor().SetGestureProperties( pan );
296 }
297
298 PanGestureDetector::PanGestureDetector( const SceneGraph::PanGesture& sceneObject )
299 : GestureDetector(Gesture::Pan, &sceneObject ),
300   mMinimumTouches(1),
301   mMaximumTouches(1)
302 {
303 }
304
305 PanGestureDetector::~PanGestureDetector()
306 {
307 }
308
309 const SceneGraph::PanGesture& PanGestureDetector::GetPanGestureSceneObject() const
310 {
311   return static_cast<const SceneGraph::PanGesture&>( GetSceneObject() );
312 }
313
314 void PanGestureDetector::OnActorAttach(Actor& actor)
315 {
316   // Do nothing
317 }
318
319 void PanGestureDetector::OnActorDetach(Actor& actor)
320 {
321   // Do nothing
322 }
323
324 void PanGestureDetector::OnActorDestroyed(Object& object)
325 {
326   // Do nothing
327 }
328
329 void PanGestureDetector::SetDefaultProperty( Property::Index index, const Property::Value& property )
330 {
331   // None of our properties should be settable from Public API
332 }
333
334 Property::Value PanGestureDetector::GetDefaultProperty( Property::Index index ) const
335 {
336   return GetDefaultPropertyCurrentValue( index ); // Scene-graph only properties
337 }
338
339 Property::Value PanGestureDetector::GetDefaultPropertyCurrentValue( Property::Index index ) const
340 {
341   Property::Value value;
342
343   switch ( index )
344   {
345     case Dali::PanGestureDetector::Property::SCREEN_POSITION:
346     {
347       value = GetPanGestureSceneObject().GetScreenPositionProperty().Get();
348       break;
349     }
350
351     case Dali::PanGestureDetector::Property::SCREEN_DISPLACEMENT:
352     {
353       value = GetPanGestureSceneObject().GetScreenDisplacementProperty().Get();
354       break;
355     }
356
357     case Dali::PanGestureDetector::Property::SCREEN_VELOCITY:
358     {
359       value = GetPanGestureSceneObject().GetScreenVelocityProperty().Get();
360       break;
361     }
362
363     case Dali::PanGestureDetector::Property::LOCAL_POSITION:
364     {
365       value = GetPanGestureSceneObject().GetLocalPositionProperty().Get();
366       break;
367     }
368
369     case Dali::PanGestureDetector::Property::LOCAL_DISPLACEMENT:
370     {
371       value = GetPanGestureSceneObject().GetLocalDisplacementProperty().Get();
372       break;
373     }
374
375     case Dali::PanGestureDetector::Property::LOCAL_VELOCITY:
376     {
377       value = GetPanGestureSceneObject().GetLocalVelocityProperty().Get();
378       break;
379     }
380
381     case Dali::PanGestureDetector::Property::PANNING:
382     {
383       value = GetPanGestureSceneObject().GetPanningProperty().Get();
384       break;
385     }
386
387     default:
388     {
389       DALI_ASSERT_ALWAYS(false && "PanGestureDetector Property index invalid" ); // should not come here
390       break;
391     }
392   }
393
394   return value;
395 }
396
397 const PropertyInputImpl* PanGestureDetector::GetSceneObjectInputProperty( Property::Index index ) const
398 {
399   const PropertyInputImpl* property = nullptr;
400
401   switch ( index )
402   {
403     case Dali::PanGestureDetector::Property::SCREEN_POSITION:
404     {
405       property = &GetPanGestureSceneObject().GetScreenPositionProperty();
406       break;
407     }
408
409     case Dali::PanGestureDetector::Property::SCREEN_DISPLACEMENT:
410     {
411       property = &GetPanGestureSceneObject().GetScreenDisplacementProperty();
412       break;
413     }
414
415     case Dali::PanGestureDetector::Property::SCREEN_VELOCITY:
416     {
417       property = &GetPanGestureSceneObject().GetScreenVelocityProperty();
418       break;
419     }
420
421     case Dali::PanGestureDetector::Property::LOCAL_POSITION:
422     {
423       property = &GetPanGestureSceneObject().GetLocalPositionProperty();
424       break;
425     }
426
427     case Dali::PanGestureDetector::Property::LOCAL_DISPLACEMENT:
428     {
429       property = &GetPanGestureSceneObject().GetLocalDisplacementProperty();
430       break;
431     }
432
433     case Dali::PanGestureDetector::Property::LOCAL_VELOCITY:
434     {
435       property = &GetPanGestureSceneObject().GetLocalVelocityProperty();
436       break;
437     }
438
439     case Dali::PanGestureDetector::Property::PANNING:
440     {
441       property = &GetPanGestureSceneObject().GetPanningProperty();
442       break;
443     }
444
445     default:
446       break;
447   }
448   if( !property )
449   {
450     // not our property, ask base
451     property = Object::GetSceneObjectInputProperty( index );
452   }
453
454   return property;
455 }
456
457 } // namespace Internal
458
459 } // namespace Dali