Updated all code to new format
[platform/core/uifw/dali-core.git] / dali / internal / event / events / tap-gesture / tap-gesture-processor.cpp
1 /*
2  * Copyright (c) 2021 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/tap-gesture/tap-gesture-processor.h>
20
21 // EXTERNAL INCLUDES
22 #include <algorithm>
23
24 // INTERNAL INCLUDES
25 #include <dali/integration-api/debug.h>
26 #include <dali/internal/event/actors/actor-impl.h>
27 #include <dali/internal/event/common/scene-impl.h>
28 #include <dali/internal/event/events/gesture-requests.h>
29 #include <dali/internal/event/events/tap-gesture/tap-gesture-event.h>
30 #include <dali/internal/event/events/tap-gesture/tap-gesture-impl.h>
31 #include <dali/internal/event/events/tap-gesture/tap-gesture-recognizer.h>
32 #include <dali/internal/event/render-tasks/render-task-impl.h>
33 #include <dali/public-api/actors/actor.h>
34 #include <dali/public-api/common/dali-common.h>
35 #include <dali/public-api/events/tap-gesture.h>
36 #include <dali/public-api/math/vector2.h>
37
38 namespace Dali
39 {
40 namespace Internal
41 {
42 namespace
43 {
44 /**
45  * Creates a TapGesture and asks the specified detector to emit its detected signal.
46  * @param[in]  actor             The actor on which a tap has occurred.
47  * @param[in]  gestureDetectors  A reference to gesture detectors that should emit the signal.
48  * @param[in]  tapEvent          The tapEvent received from the adaptor.
49  * @param[in]  localPoint        Relative to the actor attached to the detector.
50  */
51 void EmitTapSignal(
52   Actor*                          actor,
53   const GestureDetectorContainer& gestureDetectors,
54   const TapGestureEvent&          tapEvent,
55   Vector2                         localPoint)
56 {
57   Internal::TapGesturePtr tap(new Internal::TapGesture(tapEvent.state));
58   tap->SetTime(tapEvent.time);
59   tap->SetNumberOfTaps(tapEvent.numberOfTaps);
60   tap->SetNumberOfTouches(tapEvent.numberOfTouches);
61   tap->SetScreenPoint(tapEvent.point);
62   tap->SetLocalPoint(localPoint);
63
64   Dali::Actor                                    actorHandle(actor);
65   const GestureDetectorContainer::const_iterator endIter = gestureDetectors.end();
66   for(GestureDetectorContainer::const_iterator iter = gestureDetectors.begin(); iter != endIter; ++iter)
67   {
68     static_cast<TapGestureDetector*>(*iter)->EmitTapGestureSignal(actorHandle, Dali::TapGesture(tap.Get()));
69   }
70 }
71
72 } // unnamed namespace
73
74 TapGestureProcessor::TapGestureProcessor()
75 : GestureProcessor(GestureType::TAP),
76   mTapGestureDetectors(),
77   mMinTapsRequired(1),
78   mMaxTapsRequired(1),
79   mMinTouchesRequired(1),
80   mMaxTouchesRequired(1),
81   mCurrentTapEvent(nullptr),
82   mPossibleProcessed(false)
83 {
84 }
85
86 TapGestureProcessor::~TapGestureProcessor() = default;
87
88 void TapGestureProcessor::Process(Scene& scene, const TapGestureEvent& tapEvent)
89 {
90   switch(tapEvent.state)
91   {
92     case GestureState::POSSIBLE:
93     {
94       // Do a hit test and if an actor has been hit then save to see if tap event is still valid on a tap( same actor being hit )
95       HitTestAlgorithm::Results hitTestResults;
96       if(HitTest(scene, tapEvent.point, hitTestResults))
97       {
98         SetActor(&GetImplementation(hitTestResults.actor));
99         mCurrentTapActor.SetActor(GetCurrentGesturedActor());
100
101         // Indicate that we've processed a touch down. Bool should be sufficient as a change in actor will result in a cancellation
102         mPossibleProcessed = true;
103       }
104       else
105       {
106         ResetActor();
107       }
108       break;
109     }
110
111     case GestureState::STARTED:
112     {
113       // Ensure that we're processing a hit on the current actor and that we've already processed a touch down
114       HitTestAlgorithm::Results hitTestResults;
115       if(GetCurrentGesturedActor() && HitTest(scene, tapEvent.point, hitTestResults) && mPossibleProcessed)
116       {
117         // Check that this actor is still the one that was used for the last touch down ?
118         if(mCurrentTapActor.GetActor() == &GetImplementation(hitTestResults.actor))
119         {
120           mCurrentTapEvent = &tapEvent;
121           ProcessAndEmit(hitTestResults);
122         }
123         mCurrentTapEvent   = nullptr;
124         mPossibleProcessed = false;
125       }
126       break;
127     }
128
129     case GestureState::CANCELLED:
130     {
131       mPossibleProcessed = false;
132       ResetActor();
133       break;
134     }
135
136     case GestureState::CONTINUING:
137     {
138       DALI_ABORT("Incorrect state received from Integration layer: CONTINUING\n");
139       break;
140     }
141     case GestureState::FINISHED:
142     {
143       DALI_ABORT("Incorrect state received from Integration layer: FINISHED\n");
144       break;
145     }
146     case GestureState::CLEAR:
147     {
148       DALI_ABORT("Incorrect state received from Integration layer: CLEAR\n");
149       break;
150     }
151   }
152 }
153
154 void TapGestureProcessor::AddGestureDetector(TapGestureDetector* gestureDetector, Scene& scene)
155 {
156   bool firstRegistration(mTapGestureDetectors.empty());
157
158   mTapGestureDetectors.push_back(gestureDetector);
159
160   const unsigned int minTapsRequired = gestureDetector->GetMinimumTapsRequired();
161   const unsigned int maxTapsRequired = gestureDetector->GetMaximumTapsRequired();
162   const unsigned int touchesRequired = gestureDetector->GetTouchesRequired();
163
164   DALI_ASSERT_ALWAYS(minTapsRequired <= maxTapsRequired && "Minimum taps requested is greater than the maximum requested");
165
166   if(firstRegistration)
167   {
168     // If this is the first tap gesture detector that has been added, then our minimum and maximum
169     // requirements are the same as each other.
170
171     mMinTapsRequired    = minTapsRequired;
172     mMaxTapsRequired    = maxTapsRequired;
173     mMinTouchesRequired = mMaxTouchesRequired = touchesRequired;
174
175     TapGestureRequest request;
176     request.minTaps    = mMinTapsRequired;
177     request.maxTaps    = mMaxTapsRequired;
178     request.minTouches = mMinTouchesRequired;
179     request.maxTouches = mMaxTouchesRequired;
180
181     Size size          = scene.GetSize();
182     mGestureRecognizer = new TapGestureRecognizer(*this, Vector2(size.width, size.height), static_cast<const TapGestureRequest&>(request));
183   }
184   else
185   {
186     // If we have already registered for tap gesture detection before then we need to check our
187     // minimum and maximums and see if our gesture detection requirements have changed, if they
188     // have, then we should ask the adaptor to update its detection policy.
189
190     // This is quicker than calling UpdateDetection as there is no need to iterate through the container
191
192     unsigned int minTaps    = mMinTapsRequired < minTapsRequired ? mMinTapsRequired : minTapsRequired;
193     unsigned int maxTaps    = mMaxTapsRequired > maxTapsRequired ? mMaxTapsRequired : maxTapsRequired;
194     unsigned int minTouches = mMinTouchesRequired < touchesRequired ? mMinTouchesRequired : touchesRequired;
195     unsigned int maxTouches = mMaxTouchesRequired > touchesRequired ? mMaxTouchesRequired : touchesRequired;
196
197     if((minTaps != mMinTapsRequired) || (maxTaps != mMaxTapsRequired) ||
198        (minTouches != mMinTouchesRequired) || (maxTouches != mMaxTouchesRequired))
199     {
200       TapGestureRequest request;
201       request.minTaps = mMinTapsRequired = minTaps;
202       request.maxTaps = mMaxTapsRequired = maxTaps;
203       request.minTouches = mMinTouchesRequired = minTouches;
204       request.maxTouches = mMaxTouchesRequired = maxTouches;
205
206       mGestureRecognizer->Update(request);
207     }
208   }
209 }
210
211 void TapGestureProcessor::RemoveGestureDetector(TapGestureDetector* gestureDetector)
212 {
213   // Find detector ...
214   TapGestureDetectorContainer::iterator endIter = std::remove(mTapGestureDetectors.begin(), mTapGestureDetectors.end(), gestureDetector);
215   DALI_ASSERT_DEBUG(endIter != mTapGestureDetectors.end());
216
217   // ... and remove it
218   mTapGestureDetectors.erase(endIter, mTapGestureDetectors.end());
219
220   if(mTapGestureDetectors.empty())
221   {
222     mGestureRecognizer = nullptr;
223
224     ResetActor();
225   }
226   else
227   {
228     UpdateDetection();
229   }
230 }
231
232 void TapGestureProcessor::GestureDetectorUpdated(TapGestureDetector* gestureDetector)
233 {
234   DALI_ASSERT_DEBUG(find(mTapGestureDetectors.begin(), mTapGestureDetectors.end(), gestureDetector) != mTapGestureDetectors.end());
235
236   const unsigned int minTapsRequired = gestureDetector->GetMinimumTapsRequired();
237   const unsigned int maxTapsRequired = gestureDetector->GetMaximumTapsRequired();
238
239   DALI_ASSERT_ALWAYS(minTapsRequired <= maxTapsRequired && "Minimum taps requested is greater than the maximum requested");
240
241   UpdateDetection();
242 }
243
244 void TapGestureProcessor::UpdateDetection()
245 {
246   DALI_ASSERT_DEBUG(!mTapGestureDetectors.empty());
247
248   unsigned int minTaps    = UINT_MAX;
249   unsigned int maxTaps    = 0;
250   unsigned int minTouches = UINT_MAX;
251   unsigned int maxTouches = 0;
252
253   for(TapGestureDetectorContainer::iterator iter = mTapGestureDetectors.begin(), endIter = mTapGestureDetectors.end(); iter != endIter; ++iter)
254   {
255     TapGestureDetector* detector(*iter);
256
257     if(detector)
258     {
259       const unsigned int minTapsRequired = detector->GetMinimumTapsRequired();
260       const unsigned int maxTapsRequired = detector->GetMaximumTapsRequired();
261       const unsigned int touchesRequired = detector->GetTouchesRequired();
262
263       minTaps    = minTapsRequired < minTaps ? minTapsRequired : minTaps;
264       maxTaps    = maxTapsRequired > maxTaps ? maxTapsRequired : maxTaps;
265       minTouches = touchesRequired < minTouches ? touchesRequired : minTouches;
266       maxTouches = touchesRequired > maxTouches ? touchesRequired : maxTouches;
267     }
268   }
269
270   if((minTaps != mMinTapsRequired) || (maxTaps != mMaxTapsRequired) ||
271      (minTouches != mMinTouchesRequired) || (maxTouches != mMaxTouchesRequired))
272   {
273     TapGestureRequest request;
274     request.minTaps = mMinTapsRequired = minTaps;
275     request.maxTaps = mMaxTapsRequired = maxTaps;
276     request.minTouches = mMinTouchesRequired = minTouches;
277     request.maxTouches = mMaxTouchesRequired = maxTouches;
278
279     mGestureRecognizer->Update(request);
280   }
281 }
282
283 bool TapGestureProcessor::CheckGestureDetector(GestureDetector* detector, Actor* actor)
284 {
285   DALI_ASSERT_DEBUG(mCurrentTapEvent);
286
287   TapGestureDetector* tapDetector(static_cast<TapGestureDetector*>(detector));
288
289   return ((tapDetector->GetMinimumTapsRequired() <= mCurrentTapEvent->numberOfTaps) && (tapDetector->GetMaximumTapsRequired() >= mCurrentTapEvent->numberOfTaps)) &&
290          (tapDetector->GetTouchesRequired() == mCurrentTapEvent->numberOfTouches);
291 }
292
293 void TapGestureProcessor::EmitGestureSignal(Actor* actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates)
294 {
295   DALI_ASSERT_DEBUG(mCurrentTapEvent);
296
297   EmitTapSignal(actor, gestureDetectors, *mCurrentTapEvent, actorCoordinates);
298 }
299
300 } // namespace Internal
301
302 } // namespace Dali