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 #include "base/json/json_util.h"
19 #include "base/log/log.h"
20
21 namespace OHOS::Ace {
22 namespace {
23
GetSwipeDirection(const TouchEvent & firstPoint,const TouchEvent & lastPoint)24 SwipeEventInfo::SwipeDirection GetSwipeDirection(const TouchEvent& firstPoint, const TouchEvent& lastPoint)
25 {
26 static const double duration = 15.0;
27 auto xOffset = lastPoint.x - firstPoint.x;
28 auto yOffset = lastPoint.y - firstPoint.y;
29 if (std::abs(xOffset) > std::abs(yOffset)) {
30 if (std::abs(xOffset) < duration) {
31 return SwipeEventInfo::SwipeDirection::NONE;
32 }
33 return xOffset > 0.0 ? SwipeEventInfo::SwipeDirection::RIGHT : SwipeEventInfo::SwipeDirection::LEFT;
34 } else {
35 if (std::abs(yOffset) < duration) {
36 return SwipeEventInfo::SwipeDirection::NONE;
37 }
38 return yOffset > 0.0 ? SwipeEventInfo::SwipeDirection::DOWN : SwipeEventInfo::SwipeDirection::UP;
39 }
40 }
41
GetSwipeDistance(SwipeEventInfo::SwipeDirection direction,const TouchEvent & firstPoint,const TouchEvent & lastPoint)42 float GetSwipeDistance(
43 SwipeEventInfo::SwipeDirection direction, const TouchEvent& firstPoint, const TouchEvent& lastPoint)
44 {
45 if (direction == SwipeEventInfo::SwipeDirection::RIGHT) {
46 return (lastPoint.x - firstPoint.x);
47 } else if (direction == SwipeEventInfo::SwipeDirection::LEFT) {
48 return (firstPoint.x - lastPoint.x);
49 } else if (direction == SwipeEventInfo::SwipeDirection::UP) {
50 return (firstPoint.y - lastPoint.y);
51 } else if (direction == SwipeEventInfo::SwipeDirection::DOWN) {
52 return (lastPoint.y - firstPoint.y);
53 } else {
54 return 0;
55 }
56 }
57
58 } // namespace
59
ToJsonParamInfo() const60 std::string SwipeEventInfo::ToJsonParamInfo() const
61 {
62 static std::unordered_map<SwipeEventInfo::SwipeDirection, std::string> conventMap {
63 { SwipeEventInfo::SwipeDirection::RIGHT, "right" },
64 { SwipeEventInfo::SwipeDirection::LEFT, "left" },
65 { SwipeEventInfo::SwipeDirection::UP, "up" },
66 { SwipeEventInfo::SwipeDirection::DOWN, "down" },
67 };
68 auto jsonValue = JsonUtil::Create(true);
69 jsonValue->Put("type", GetType().c_str());
70 jsonValue->Put("timestamp", static_cast<double>(GetTimeStamp().time_since_epoch().count()));
71 jsonValue->Put("direction", conventMap[swipeDirection_].c_str());
72 jsonValue->Put("distance", distance_);
73 return jsonValue->ToString();
74 }
75
HandleSwipeEvent(const TouchEvent & point,uint32_t stage)76 bool SwipeRecognizer::HandleSwipeEvent(const TouchEvent& point, uint32_t stage)
77 {
78 switch (point.type) {
79 case TouchType::DOWN: {
80 // reset the recognizer status.
81 auto& status = statusMap_[point.id];
82 status.first = point;
83 status.second = false;
84 break;
85 }
86 case TouchType::UP: {
87 auto callback = swipeCallback_[stage];
88 auto callbackCatch = swipeCatchCallback_[stage];
89 auto& status = statusMap_[point.id];
90
91 if (status.second && callbackCatch) {
92 auto direction = GetSwipeDirection(status.first, point);
93 if (direction == SwipeEventInfo::SwipeDirection::NONE) {
94 return true;
95 }
96 callbackCatch(SwipeEventInfo(direction, GetSwipeDistance(direction, status.first, point)));
97 return false;
98 }
99
100 if (status.second && callback) {
101 auto direction = GetSwipeDirection(status.first, point);
102 if (direction == SwipeEventInfo::SwipeDirection::NONE) {
103 return true;
104 }
105 callback(SwipeEventInfo(direction, GetSwipeDistance(direction, status.first, point)));
106 }
107 break;
108 }
109 case TouchType::MOVE: {
110 auto& status = statusMap_[point.id];
111 status.second = true;
112 break;
113 }
114 case TouchType::CANCEL: {
115 auto& status = statusMap_[point.id];
116 status.second = false;
117 break;
118 }
119 default:
120 LOGW("unknown type point type.");
121 }
122 return true;
123 }
124
HandleEvent(const TouchEvent & point)125 bool SwipeRecognizer::HandleEvent(const TouchEvent& point)
126 {
127 return HandleSwipeEvent(point, EventStage::BUBBLE);
128 }
129
DispatchEvent(const TouchEvent & point)130 bool SwipeRecognizer::DispatchEvent(const TouchEvent& point)
131 {
132 HandleSwipeEvent(point, EventStage::CAPTURE);
133
134 auto& status = statusMap_[point.id];
135 if (status.second) {
136 auto direction = GetSwipeDirection(status.first, point);
137 if (direction == SwipeEventInfo::SwipeDirection::NONE) {
138 return true;
139 }
140 auto catchCallback = swipeCatchCallback_[EventStage::CAPTURE];
141 if (catchCallback) {
142 catchCallback(SwipeEventInfo(direction, GetSwipeDistance(direction, status.first, point)));
143 return false;
144 }
145 }
146 return true;
147 }
148
149 } // namespace OHOS::Ace
150