Merge "Clean up the code to build successfully on macOS" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / event / events / pan-gesture / pan-gesture-detector-impl.cpp
1 /*
2  * Copyright (c) 2020 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/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 uint32_t PanGestureDetector::GetMinimumTouchesRequired() const
140 {
141   return mMinimumTouches;
142 }
143
144 uint32_t 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 uint32_t PanGestureDetector::GetAngleCount() const
180 {
181   return static_cast<uint32_t>( mAngleContainer.size() );
182 }
183
184 PanGestureDetector::AngleThresholdPair PanGestureDetector::GetAngle(uint32_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 Dali::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 Dali::PanGesture& pan )
294 {
295   ThreadLocalStorage::Get().GetGestureEventProcessor().SetGestureProperties( pan );
296 }
297
298 PanGestureDetector::PanGestureDetector( const SceneGraph::PanGesture& sceneObject )
299 : GestureDetector( GestureType::PAN, &sceneObject ),
300   mMinimumTouches(1),
301   mMaximumTouches(1)
302 {
303 }
304
305 PanGestureDetector::~PanGestureDetector() = default;
306
307 const SceneGraph::PanGesture& PanGestureDetector::GetPanGestureSceneObject() const
308 {
309   return static_cast<const SceneGraph::PanGesture&>( GetSceneObject() );
310 }
311
312 void PanGestureDetector::OnActorAttach(Actor& actor)
313 {
314   // Do nothing
315 }
316
317 void PanGestureDetector::OnActorDetach(Actor& actor)
318 {
319   // Do nothing
320 }
321
322 void PanGestureDetector::OnActorDestroyed(Object& object)
323 {
324   // Do nothing
325 }
326
327 void PanGestureDetector::SetDefaultProperty( Property::Index index, const Property::Value& property )
328 {
329   // None of our properties should be settable from Public API
330 }
331
332 Property::Value PanGestureDetector::GetDefaultProperty( Property::Index index ) const
333 {
334   return GetDefaultPropertyCurrentValue( index ); // Scene-graph only properties
335 }
336
337 Property::Value PanGestureDetector::GetDefaultPropertyCurrentValue( Property::Index index ) const
338 {
339   Property::Value value;
340
341   switch ( index )
342   {
343     case Dali::PanGestureDetector::Property::SCREEN_POSITION:
344     {
345       value = GetPanGestureSceneObject().GetScreenPositionProperty().Get();
346       break;
347     }
348
349     case Dali::PanGestureDetector::Property::SCREEN_DISPLACEMENT:
350     {
351       value = GetPanGestureSceneObject().GetScreenDisplacementProperty().Get();
352       break;
353     }
354
355     case Dali::PanGestureDetector::Property::SCREEN_VELOCITY:
356     {
357       value = GetPanGestureSceneObject().GetScreenVelocityProperty().Get();
358       break;
359     }
360
361     case Dali::PanGestureDetector::Property::LOCAL_POSITION:
362     {
363       value = GetPanGestureSceneObject().GetLocalPositionProperty().Get();
364       break;
365     }
366
367     case Dali::PanGestureDetector::Property::LOCAL_DISPLACEMENT:
368     {
369       value = GetPanGestureSceneObject().GetLocalDisplacementProperty().Get();
370       break;
371     }
372
373     case Dali::PanGestureDetector::Property::LOCAL_VELOCITY:
374     {
375       value = GetPanGestureSceneObject().GetLocalVelocityProperty().Get();
376       break;
377     }
378
379     case Dali::PanGestureDetector::Property::PANNING:
380     {
381       value = GetPanGestureSceneObject().GetPanningProperty().Get();
382       break;
383     }
384
385     default:
386     {
387       DALI_ASSERT_ALWAYS(false && "PanGestureDetector Property index invalid" ); // should not come here
388       break;
389     }
390   }
391
392   return value;
393 }
394
395 const PropertyInputImpl* PanGestureDetector::GetSceneObjectInputProperty( Property::Index index ) const
396 {
397   const PropertyInputImpl* property = nullptr;
398
399   switch ( index )
400   {
401     case Dali::PanGestureDetector::Property::SCREEN_POSITION:
402     {
403       property = &GetPanGestureSceneObject().GetScreenPositionProperty();
404       break;
405     }
406
407     case Dali::PanGestureDetector::Property::SCREEN_DISPLACEMENT:
408     {
409       property = &GetPanGestureSceneObject().GetScreenDisplacementProperty();
410       break;
411     }
412
413     case Dali::PanGestureDetector::Property::SCREEN_VELOCITY:
414     {
415       property = &GetPanGestureSceneObject().GetScreenVelocityProperty();
416       break;
417     }
418
419     case Dali::PanGestureDetector::Property::LOCAL_POSITION:
420     {
421       property = &GetPanGestureSceneObject().GetLocalPositionProperty();
422       break;
423     }
424
425     case Dali::PanGestureDetector::Property::LOCAL_DISPLACEMENT:
426     {
427       property = &GetPanGestureSceneObject().GetLocalDisplacementProperty();
428       break;
429     }
430
431     case Dali::PanGestureDetector::Property::LOCAL_VELOCITY:
432     {
433       property = &GetPanGestureSceneObject().GetLocalVelocityProperty();
434       break;
435     }
436
437     case Dali::PanGestureDetector::Property::PANNING:
438     {
439       property = &GetPanGestureSceneObject().GetPanningProperty();
440       break;
441     }
442
443     default:
444       break;
445   }
446   if( !property )
447   {
448     // not our property, ask base
449     property = Object::GetSceneObjectInputProperty( index );
450   }
451
452   return property;
453 }
454
455 } // namespace Internal
456
457 } // namespace Dali