1 /*
2  * Copyright (c) 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/components_ng/event/scrollable_event.h"
17 
18 #include "base/geometry/offset.h"
19 #include "base/utils/utils.h"
20 #include "core/components_ng/base/frame_node.h"
21 #include "core/components_ng/event/gesture_event_hub.h"
22 #include "core/pipeline_ng/pipeline_context.h"
23 #include "core/components_ng/pattern/list/list_pattern.h"
24 
25 namespace OHOS::Ace::NG {
26 
ScrollableActuator(const WeakPtr<GestureEventHub> & gestureEventHub)27 ScrollableActuator::ScrollableActuator(const WeakPtr<GestureEventHub>& gestureEventHub)
28     : gestureEventHub_(gestureEventHub)
29 {}
30 
AddScrollEdgeEffect(const Axis & axis,RefPtr<ScrollEdgeEffect> & effect)31 void ScrollableActuator::AddScrollEdgeEffect(const Axis& axis, RefPtr<ScrollEdgeEffect>& effect)
32 {
33     CHECK_NULL_VOID(effect);
34     auto scrollable = scrollableEvents_[axis];
35     CHECK_NULL_VOID(scrollable);
36     effect->SetScrollable(scrollable->GetScrollable());
37     effect->InitialEdgeEffect();
38     scrollEffects_[axis] = effect;
39 }
40 
RemoveScrollEdgeEffect(const RefPtr<ScrollEdgeEffect> & effect)41 bool ScrollableActuator::RemoveScrollEdgeEffect(const RefPtr<ScrollEdgeEffect>& effect)
42 {
43     CHECK_NULL_RETURN(effect, false);
44     for (auto iter = scrollEffects_.begin(); iter != scrollEffects_.end(); ++iter) {
45         if (effect == iter->second) {
46             scrollEffects_.erase(iter);
47             return true;
48         }
49     }
50     return false;
51 }
52 
CollectTouchTarget(const OffsetF & coordinateOffset,const TouchRestrict & touchRestrict,const GetEventTargetImpl & getEventTargetImpl,TouchTestResult & result,const PointF & localPoint,const RefPtr<FrameNode> & frameNode,const RefPtr<TargetComponent> & targetComponent,ResponseLinkResult & responseLinkResult)53 void ScrollableActuator::CollectTouchTarget(const OffsetF& coordinateOffset, const TouchRestrict& touchRestrict,
54     const GetEventTargetImpl& getEventTargetImpl, TouchTestResult& result, const PointF& localPoint,
55     const RefPtr<FrameNode>& frameNode, const RefPtr<TargetComponent>& targetComponent,
56     ResponseLinkResult& responseLinkResult)
57 {
58     for (const auto& [axis, event] : scrollableEvents_) {
59         if (!event) {
60             continue;
61         }
62         if (event->GetEnabled()) {
63             if (event->InBarRegion(localPoint, touchRestrict.sourceType)) {
64                 event->BarCollectTouchTarget(
65                     coordinateOffset, getEventTargetImpl, result, frameNode, targetComponent, responseLinkResult);
66             } else if (event->InBarRectRegion(localPoint, touchRestrict.sourceType)) {
67                 event->BarCollectLongPressTarget(
68                     coordinateOffset, getEventTargetImpl, result, frameNode, targetComponent, responseLinkResult);
69                 event->CollectScrollableTouchTarget(
70                     coordinateOffset, getEventTargetImpl, result, frameNode, targetComponent, responseLinkResult);
71             } else {
72                 event->CollectScrollableTouchTarget(
73                     coordinateOffset, getEventTargetImpl, result, frameNode, targetComponent, responseLinkResult);
74             }
75         }
76         bool clickJudge = event->ClickJudge(localPoint);
77         if (event->GetEnabled() || clickJudge) {
78             InitClickRecognizer(coordinateOffset, getEventTargetImpl, frameNode, targetComponent, event, clickJudge,
79                 localPoint, touchRestrict.sourceType);
80             result.emplace_front(clickRecognizer_);
81             responseLinkResult.emplace_back(clickRecognizer_);
82         }
83         break;
84     }
85 }
86 
InitClickRecognizer(const OffsetF & coordinateOffset,const GetEventTargetImpl & getEventTargetImpl,const RefPtr<FrameNode> & frameNode,const RefPtr<TargetComponent> & targetComponent,const RefPtr<ScrollableEvent> & event,bool clickJudge,const PointF & localPoint,SourceType source)87 void ScrollableActuator::InitClickRecognizer(const OffsetF& coordinateOffset,
88     const GetEventTargetImpl& getEventTargetImpl, const RefPtr<FrameNode>& frameNode,
89     const RefPtr<TargetComponent>& targetComponent,
90     const RefPtr<ScrollableEvent>& event, bool clickJudge,
91     const PointF& localPoint, SourceType source)
92 {
93     if (!clickRecognizer_) {
94         clickRecognizer_ = MakeRefPtr<ClickRecognizer>();
95     }
96     bool isHitTestBlock = event->IsHitTestBlock(localPoint, source);
97     clickRecognizer_->SetCoordinateOffset(Offset(coordinateOffset.GetX(), coordinateOffset.GetY()));
98     clickRecognizer_->SetGetEventTargetImpl(getEventTargetImpl);
99     clickRecognizer_->SetNodeId(frameNode->GetId());
100     clickRecognizer_->AttachFrameNode(frameNode);
101     clickRecognizer_->SetTargetComponent(targetComponent);
102     clickRecognizer_->SetIsSystemGesture(true);
103     clickRecognizer_->SetRecognizerType(GestureTypeName::TAP_GESTURE);
104     clickRecognizer_->SetSysGestureJudge([isHitTestBlock, clickJudge](const RefPtr<GestureInfo>& gestureInfo,
105                                              const std::shared_ptr<BaseGestureEvent>&) -> GestureJudgeResult {
106         TAG_LOGI(
107             AceLogTag::ACE_SCROLLABLE, "Scrollable GestureJudge:%{public}d, %{public}d", isHitTestBlock, clickJudge);
108         return isHitTestBlock || clickJudge ? GestureJudgeResult::CONTINUE : GestureJudgeResult::REJECT;
109     });
110     clickRecognizer_->SetOnClick([weak = WeakClaim(RawPtr(frameNode))](const ClickInfo&) {
111         auto frameNode = weak.Upgrade();
112         CHECK_NULL_VOID(frameNode);
113         auto pattern = frameNode->GetPattern<ListPattern>();
114         CHECK_NULL_VOID(pattern);
115         auto item = pattern->GetSwiperItem().Upgrade();
116         CHECK_NULL_VOID(item);
117         item->ResetSwipeStatus();
118     });
119 }
120 
CollectScrollableTouchTarget(const OffsetF & coordinateOffset,const GetEventTargetImpl & getEventTargetImpl,TouchTestResult & result,const RefPtr<FrameNode> & frameNode,const RefPtr<TargetComponent> & targetComponent,ResponseLinkResult & responseLinkResult)121 void ScrollableEvent::CollectScrollableTouchTarget(const OffsetF& coordinateOffset,
122     const GetEventTargetImpl& getEventTargetImpl, TouchTestResult& result, const RefPtr<FrameNode>& frameNode,
123     const RefPtr<TargetComponent>& targetComponent, ResponseLinkResult& responseLinkResult)
124 {
125     if (scrollable_) {
126         scrollable_->SetGetEventTargetImpl(getEventTargetImpl);
127         scrollable_->SetCoordinateOffset(Offset(coordinateOffset.GetX(), coordinateOffset.GetY()));
128         scrollable_->OnCollectTouchTarget(result, frameNode, targetComponent, responseLinkResult);
129     }
130 }
131 } // namespace OHOS::Ace::NG
132