1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/gestures/swipe_recognizer.h"
17 
18 namespace OHOS::Ace {
19 namespace {
20 
GetSwipeDirection(const TouchEvent & firstPoint,const TouchEvent & lastPoint)21 SwipeEventInfo::SwipeDirection GetSwipeDirection(const TouchEvent& firstPoint, const TouchEvent& lastPoint)
22 {
23     static const double duration = 15.0;
24     auto xOffset = lastPoint.x - firstPoint.x;
25     auto yOffset = lastPoint.y - firstPoint.y;
26     if (std::abs(xOffset) > std::abs(yOffset)) {
27         if (std::abs(xOffset) < duration) {
28             return SwipeEventInfo::SwipeDirection::NONE;
29         }
30         return xOffset > 0.0 ? SwipeEventInfo::SwipeDirection::RIGHT : SwipeEventInfo::SwipeDirection::LEFT;
31     } else {
32         if (std::abs(yOffset) < duration) {
33             return SwipeEventInfo::SwipeDirection::NONE;
34         }
35         return yOffset > 0.0 ? SwipeEventInfo::SwipeDirection::DOWN : SwipeEventInfo::SwipeDirection::UP;
36     }
37 }
38 
GetSwipeDistance(SwipeEventInfo::SwipeDirection direction,const TouchEvent & firstPoint,const TouchEvent & lastPoint)39 float GetSwipeDistance(
40     SwipeEventInfo::SwipeDirection direction, const TouchEvent& firstPoint, const TouchEvent& lastPoint)
41 {
42     if (direction == SwipeEventInfo::SwipeDirection::RIGHT) {
43         return (lastPoint.x - firstPoint.x);
44     } else if (direction == SwipeEventInfo::SwipeDirection::LEFT) {
45         return (firstPoint.x - lastPoint.x);
46     } else if (direction == SwipeEventInfo::SwipeDirection::UP) {
47         return (firstPoint.y - lastPoint.y);
48     } else if (direction == SwipeEventInfo::SwipeDirection::DOWN) {
49         return (lastPoint.y - firstPoint.y);
50     } else {
51         return 0;
52     }
53 }
54 
55 } // namespace
56 
ToJsonParamInfo() const57 std::string SwipeEventInfo::ToJsonParamInfo() const
58 {
59     static std::unordered_map<SwipeEventInfo::SwipeDirection, std::string> conventMap {
60         { SwipeEventInfo::SwipeDirection::RIGHT, "right" },
61         { SwipeEventInfo::SwipeDirection::LEFT, "left" },
62         { SwipeEventInfo::SwipeDirection::UP, "up" },
63         { SwipeEventInfo::SwipeDirection::DOWN, "down" },
64     };
65     auto jsonValue = JsonUtil::Create(true);
66     jsonValue->Put("type", GetType().c_str());
67     jsonValue->Put("timestamp", static_cast<double>(GetTimeStamp().time_since_epoch().count()));
68     jsonValue->Put("direction", conventMap[swipeDirection_].c_str());
69     jsonValue->Put("distance", distance_);
70     return jsonValue->ToString();
71 }
72 
HandleSwipeEvent(const TouchEvent & point,uint32_t stage)73 bool SwipeRecognizer::HandleSwipeEvent(const TouchEvent& point, uint32_t stage)
74 {
75     switch (point.type) {
76         case TouchType::DOWN: {
77             // reset the recognizer status.
78             auto& status = statusMap_[point.id];
79             status.first = point;
80             status.second = false;
81             break;
82         }
83         case TouchType::UP: {
84             auto callback = swipeCallback_[stage];
85             auto callbackCatch = swipeCatchCallback_[stage];
86             auto& status = statusMap_[point.id];
87 
88             if (status.second && callbackCatch) {
89                 auto direction = GetSwipeDirection(status.first, point);
90                 if (direction == SwipeEventInfo::SwipeDirection::NONE) {
91                     return true;
92                 }
93                 callbackCatch(SwipeEventInfo(direction, GetSwipeDistance(direction, status.first, point)));
94                 return false;
95             }
96 
97             if (status.second && callback) {
98                 auto direction = GetSwipeDirection(status.first, point);
99                 if (direction == SwipeEventInfo::SwipeDirection::NONE) {
100                     return true;
101                 }
102                 callback(SwipeEventInfo(direction, GetSwipeDistance(direction, status.first, point)));
103             }
104             break;
105         }
106         case TouchType::MOVE: {
107             auto& status = statusMap_[point.id];
108             status.second = true;
109             break;
110         }
111         case TouchType::CANCEL: {
112             auto& status = statusMap_[point.id];
113             status.second = false;
114             break;
115         }
116         default:
117             LOGW("unknown type point type.");
118     }
119     return true;
120 }
121 
HandleEvent(const TouchEvent & point)122 bool SwipeRecognizer::HandleEvent(const TouchEvent& point)
123 {
124     return HandleSwipeEvent(point, EventStage::BUBBLE);
125 }
126 
DispatchEvent(const TouchEvent & point)127 bool SwipeRecognizer::DispatchEvent(const TouchEvent& point)
128 {
129     HandleSwipeEvent(point, EventStage::CAPTURE);
130 
131     auto& status = statusMap_[point.id];
132     if (status.second) {
133         auto direction = GetSwipeDirection(status.first, point);
134         if (direction == SwipeEventInfo::SwipeDirection::NONE) {
135             return true;
136         }
137         auto catchCallback = swipeCatchCallback_[EventStage::CAPTURE];
138         if (catchCallback) {
139             catchCallback(SwipeEventInfo(direction, GetSwipeDistance(direction, status.first, point)));
140             return false;
141         }
142     }
143     return true;
144 }
145 
146 } // namespace OHOS::Ace
147