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