2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/event/events/pan-gesture-detector-impl.h>
22 #include <cstring> // for strcmp
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>
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 )
60 const char* const SIGNAL_PAN_DETECTED = "panDetected";
64 return Dali::PanGestureDetector::New();
67 TypeRegistration mType( typeid(Dali::PanGestureDetector), typeid(Dali::GestureDetector), Create, PanGestureDetectorDefaultProperties );
69 SignalConnectorType signalConnector1( mType, SIGNAL_PAN_DETECTED, &PanGestureDetector::DoConnectSignal );
71 #if defined(DEBUG_ENABLED)
72 Integration::Log::Filter* gLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_PAN_GESTURE_DETECTOR");
76 * Returns the angle going in the opposite direction to that specified by angle.
78 float GetOppositeAngle( float angle )
80 // Calculate the opposite angle so that we cover both directions.
93 } // unnamed namespace
95 PanGestureDetectorPtr PanGestureDetector::New()
97 const SceneGraph::PanGesture& sceneObject = ThreadLocalStorage::Get().GetGestureEventProcessor().GetPanGestureProcessor().GetSceneObject();
98 return new PanGestureDetector( sceneObject );
101 void PanGestureDetector::SetMinimumTouchesRequired(unsigned int minimum)
103 DALI_ASSERT_ALWAYS( minimum > 0 && "Can only set a positive number of required touches" );
105 if (mMinimumTouches != minimum)
107 DALI_LOG_INFO( gLogFilter, Debug::Concise, "Minimum Touches Set: %d\n", minimum );
109 mMinimumTouches = minimum;
111 if (!mAttachedActors.empty())
113 DALI_LOG_INFO( gLogFilter, Debug::General, "Updating Gesture Detector\n");
115 mGestureEventProcessor.GestureDetectorUpdated(this);
120 void PanGestureDetector::SetMaximumTouchesRequired(unsigned int maximum)
122 DALI_ASSERT_ALWAYS( maximum > 0 && "Can only set a positive number of maximum touches" );
124 if (mMaximumTouches != maximum)
126 DALI_LOG_INFO( gLogFilter, Debug::Concise, "Maximum Touches Set: %d\n", maximum );
128 mMaximumTouches = maximum;
130 if (!mAttachedActors.empty())
132 DALI_LOG_INFO( gLogFilter, Debug::General, "Updating Gesture Detector\n");
134 mGestureEventProcessor.GestureDetectorUpdated(this);
139 uint32_t PanGestureDetector::GetMinimumTouchesRequired() const
141 return mMinimumTouches;
144 uint32_t PanGestureDetector::GetMaximumTouchesRequired() const
146 return mMaximumTouches;
149 void PanGestureDetector::AddAngle( Radian angle, Radian threshold )
151 threshold = fabsf( threshold ); // Ensure the threshold is positive.
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 )
158 threshold = Math::PI;
161 angle = WrapInDomain( angle, -Math::PI, Math::PI );
163 DALI_LOG_INFO( gLogFilter, Debug::Concise, "Angle Added: %.2f, Threshold: %.2f\n", Degree(angle), Degree(threshold) );
165 AngleThresholdPair pair( angle, threshold );
166 mAngleContainer.push_back( pair );
169 void PanGestureDetector::AddDirection( Radian direction, Radian threshold )
171 AddAngle( direction, threshold );
173 // Calculate the opposite angle so that we cover the entire direction.
174 direction = GetOppositeAngle( direction );
176 AddAngle( direction, threshold );
179 uint32_t PanGestureDetector::GetAngleCount() const
181 return static_cast<uint32_t>( mAngleContainer.size() );
184 PanGestureDetector::AngleThresholdPair PanGestureDetector::GetAngle(uint32_t index) const
186 PanGestureDetector::AngleThresholdPair ret( Radian(0),Radian(0) );
188 if( index < mAngleContainer.size() )
190 ret = mAngleContainer[index];
197 void PanGestureDetector::ClearAngles()
199 mAngleContainer.clear();
202 void PanGestureDetector::RemoveAngle( Radian angle )
204 angle = WrapInDomain( angle, -Math::PI, Math::PI );
206 for (AngleContainer::iterator iter = mAngleContainer.begin(), endIter = mAngleContainer.end(); iter != endIter; ++iter )
208 if ( iter->first == angle )
210 mAngleContainer.erase( iter );
216 void PanGestureDetector::RemoveDirection( Radian direction )
218 RemoveAngle( direction );
220 // Calculate the opposite angle so that we cover the entire direction.
221 direction = GetOppositeAngle( direction );
223 RemoveAngle( direction );
226 bool PanGestureDetector::RequiresDirectionalPan() const
228 // If no directional angles have been added to the container then we do not require directional panning
229 return !mAngleContainer.empty();
232 bool PanGestureDetector::CheckAngleAllowed( Radian angle ) const
234 bool allowed( false );
235 if ( mAngleContainer.empty() )
241 for ( AngleContainer::const_iterator iter = mAngleContainer.begin(), endIter = mAngleContainer.end(); iter != endIter; ++iter )
243 float angleAllowed( iter->first );
244 float threshold ( iter->second );
246 DALI_LOG_INFO( gLogFilter, Debug::General,
247 "AngleToCheck: %.2f, CompareWith: %.2f, Threshold: %.2f\n",
248 Degree(angle), Degree(angleAllowed), Degree(threshold) );
250 float relativeAngle( fabsf( WrapInDomain( angle - angleAllowed, -Math::PI, Math::PI ) ) );
251 if ( relativeAngle <= threshold )
262 void PanGestureDetector::EmitPanGestureSignal(Dali::Actor actor, const PanGesture& pan)
264 if ( !mDetectedSignal.Empty() )
266 // Guard against destruction during signal emission
267 Dali::PanGestureDetector handle( this );
269 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Emitting Signal (%p)\n", this );
271 mDetectedSignal.Emit( actor, pan );
275 bool PanGestureDetector::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
277 bool connected( true );
278 PanGestureDetector* gesture = static_cast< PanGestureDetector* >(object); // TypeRegistry guarantees that this is the correct type.
280 if ( 0 == strcmp( signalName.c_str(), SIGNAL_PAN_DETECTED ) )
282 gesture->DetectedSignal().Connect( tracker, functor );
286 // signalName does not match any signal
293 void PanGestureDetector::SetPanGestureProperties( const PanGesture& pan )
295 ThreadLocalStorage::Get().GetGestureEventProcessor().SetGestureProperties( pan );
298 PanGestureDetector::PanGestureDetector( const SceneGraph::PanGesture& sceneObject )
299 : GestureDetector(Gesture::Pan, &sceneObject ),
305 PanGestureDetector::~PanGestureDetector()
309 const SceneGraph::PanGesture& PanGestureDetector::GetPanGestureSceneObject() const
311 return static_cast<const SceneGraph::PanGesture&>( GetSceneObject() );
314 void PanGestureDetector::OnActorAttach(Actor& actor)
319 void PanGestureDetector::OnActorDetach(Actor& actor)
324 void PanGestureDetector::OnActorDestroyed(Object& object)
329 void PanGestureDetector::SetDefaultProperty( Property::Index index, const Property::Value& property )
331 // None of our properties should be settable from Public API
334 Property::Value PanGestureDetector::GetDefaultProperty( Property::Index index ) const
336 return GetDefaultPropertyCurrentValue( index ); // Scene-graph only properties
339 Property::Value PanGestureDetector::GetDefaultPropertyCurrentValue( Property::Index index ) const
341 Property::Value value;
345 case Dali::PanGestureDetector::Property::SCREEN_POSITION:
347 value = GetPanGestureSceneObject().GetScreenPositionProperty().Get();
351 case Dali::PanGestureDetector::Property::SCREEN_DISPLACEMENT:
353 value = GetPanGestureSceneObject().GetScreenDisplacementProperty().Get();
357 case Dali::PanGestureDetector::Property::SCREEN_VELOCITY:
359 value = GetPanGestureSceneObject().GetScreenVelocityProperty().Get();
363 case Dali::PanGestureDetector::Property::LOCAL_POSITION:
365 value = GetPanGestureSceneObject().GetLocalPositionProperty().Get();
369 case Dali::PanGestureDetector::Property::LOCAL_DISPLACEMENT:
371 value = GetPanGestureSceneObject().GetLocalDisplacementProperty().Get();
375 case Dali::PanGestureDetector::Property::LOCAL_VELOCITY:
377 value = GetPanGestureSceneObject().GetLocalVelocityProperty().Get();
381 case Dali::PanGestureDetector::Property::PANNING:
383 value = GetPanGestureSceneObject().GetPanningProperty().Get();
389 DALI_ASSERT_ALWAYS(false && "PanGestureDetector Property index invalid" ); // should not come here
397 const PropertyInputImpl* PanGestureDetector::GetSceneObjectInputProperty( Property::Index index ) const
399 const PropertyInputImpl* property = nullptr;
403 case Dali::PanGestureDetector::Property::SCREEN_POSITION:
405 property = &GetPanGestureSceneObject().GetScreenPositionProperty();
409 case Dali::PanGestureDetector::Property::SCREEN_DISPLACEMENT:
411 property = &GetPanGestureSceneObject().GetScreenDisplacementProperty();
415 case Dali::PanGestureDetector::Property::SCREEN_VELOCITY:
417 property = &GetPanGestureSceneObject().GetScreenVelocityProperty();
421 case Dali::PanGestureDetector::Property::LOCAL_POSITION:
423 property = &GetPanGestureSceneObject().GetLocalPositionProperty();
427 case Dali::PanGestureDetector::Property::LOCAL_DISPLACEMENT:
429 property = &GetPanGestureSceneObject().GetLocalDisplacementProperty();
433 case Dali::PanGestureDetector::Property::LOCAL_VELOCITY:
435 property = &GetPanGestureSceneObject().GetLocalVelocityProperty();
439 case Dali::PanGestureDetector::Property::PANNING:
441 property = &GetPanGestureSceneObject().GetPanningProperty();
450 // not our property, ask base
451 property = Object::GetSceneObjectInputProperty( index );
457 } // namespace Internal