• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "core/components_ng/event/target_component.h"
19 #include "core/components_ng/gestures/recognizers/parallel_recognizer.h"
20 #include "core/components_ng/pattern/list/list_pattern.h"
21 #include "core/components_ng/pattern/scroll/scroll_edge_effect.h"
22 #include "core/components_ng/pattern/scroll/scroll_pattern.h"
23 #include "core/components_ng/pattern/scrollable/scrollable.h"
24 
25 namespace OHOS::Ace::NG {
26 
ScrollableEvent(Axis axis)27 ScrollableEvent::ScrollableEvent(Axis axis) : axis_(axis) {};
28 ScrollableEvent::~ScrollableEvent() = default;
29 
ScrollableActuator(const WeakPtr<GestureEventHub> & gestureEventHub)30 ScrollableActuator::ScrollableActuator(const WeakPtr<GestureEventHub>& gestureEventHub)
31     : gestureEventHub_(gestureEventHub)
32 {}
33 
SetAxis(Axis axis)34 void ScrollableEvent::SetAxis(Axis axis)
35 {
36     axis_ = axis;
37     if (scrollable_) {
38         scrollable_->SetAxis(axis);
39     }
40 }
41 
SetScrollable(const RefPtr<Scrollable> & scrollable)42 void ScrollableEvent::SetScrollable(const RefPtr<Scrollable>& scrollable)
43 {
44     scrollable_ = scrollable;
45 }
46 
GetScrollable() const47 const RefPtr<Scrollable>& ScrollableEvent::GetScrollable() const
48 {
49     return scrollable_;
50 }
51 
Idle() const52 bool ScrollableEvent::Idle() const
53 {
54     if (scrollable_) {
55         return scrollable_->Idle();
56     }
57     return true;
58 }
59 
IsHitTestBlock(const PointF & localPoint,SourceType source) const60 bool ScrollableEvent::IsHitTestBlock(const PointF& localPoint, SourceType source) const
61 {
62     if (source == SourceType::MOUSE && InBarRectRegion(localPoint, source)) {
63         return false;
64     }
65     if (scrollable_ && !scrollable_->Idle() &&
66         std::abs(scrollable_->GetCurrentVelocity()) > PipelineBase::Vp2PxWithCurrentDensity(HTMBLOCK_VELOCITY)) {
67         return true;
68     }
69     if (getAnimateVelocityCallback_) {
70         return std::abs(getAnimateVelocityCallback_()) > PipelineBase::Vp2PxWithCurrentDensity(HTMBLOCK_VELOCITY);
71     }
72     return false;
73 }
74 
AddPreviewMenuHandleDragEnd(GestureEventFunc && actionEnd)75 void ScrollableEvent::AddPreviewMenuHandleDragEnd(GestureEventFunc&& actionEnd)
76 {
77     if (scrollable_) {
78         scrollable_->AddPreviewMenuHandleDragEnd(std::move(actionEnd));
79     }
80 }
81 
AddScrollEdgeEffect(const Axis & axis,RefPtr<ScrollEdgeEffect> & effect)82 void ScrollableActuator::AddScrollEdgeEffect(const Axis& axis, RefPtr<ScrollEdgeEffect>& effect)
83 {
84     CHECK_NULL_VOID(effect);
85     auto scrollable = scrollableEvents_[axis];
86     CHECK_NULL_VOID(scrollable);
87     effect->SetScrollable(scrollable->GetScrollable());
88     effect->InitialEdgeEffect();
89     scrollEffects_[axis] = effect;
90 }
91 
RemoveScrollEdgeEffect(const RefPtr<ScrollEdgeEffect> & effect)92 bool ScrollableActuator::RemoveScrollEdgeEffect(const RefPtr<ScrollEdgeEffect>& effect)
93 {
94     CHECK_NULL_RETURN(effect, false);
95     for (auto iter = scrollEffects_.begin(); iter != scrollEffects_.end(); ++iter) {
96         if (effect == iter->second) {
97             scrollEffects_.erase(iter);
98             return true;
99         }
100     }
101     return false;
102 }
103 
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,int32_t touchId)104 void ScrollableActuator::CollectTouchTarget(const OffsetF& coordinateOffset, const TouchRestrict& touchRestrict,
105     const GetEventTargetImpl& getEventTargetImpl, TouchTestResult& result, const PointF& localPoint,
106     const RefPtr<FrameNode>& frameNode, const RefPtr<TargetComponent>& targetComponent,
107     ResponseLinkResult& responseLinkResult, int32_t touchId)
108 {
109     for (const auto& [axis, event] : scrollableEvents_) {
110         if (!event) {
111             continue;
112         }
113         if (event->GetEnabled()) {
114             if (event->InBarRegion(localPoint, touchRestrict.sourceType)) {
115                 event->BarCollectTouchTarget(
116                     coordinateOffset, getEventTargetImpl, result, frameNode, targetComponent, responseLinkResult);
117             } else if (event->InBarRectRegion(localPoint, touchRestrict.sourceType)) {
118                 event->BarCollectLongPressTarget(
119                     coordinateOffset, getEventTargetImpl, result, frameNode, targetComponent, responseLinkResult);
120                 event->CollectScrollableTouchTarget(coordinateOffset, getEventTargetImpl, result, frameNode,
121                     targetComponent, responseLinkResult, touchId);
122                 event->BarRectCollectTouchTarget(
123                     coordinateOffset, getEventTargetImpl, result, frameNode, targetComponent, responseLinkResult);
124             } else {
125                 event->CollectScrollableTouchTarget(coordinateOffset, getEventTargetImpl, result, frameNode,
126                     targetComponent, responseLinkResult, touchId);
127             }
128         }
129         bool clickJudge = event->ClickJudge(localPoint);
130         if (event->GetEnabled() || clickJudge) {
131             InitClickRecognizer(coordinateOffset, getEventTargetImpl, frameNode, targetComponent, event, clickJudge,
132                 localPoint, touchRestrict.sourceType);
133             result.emplace_front(clickRecognizer_);
134             responseLinkResult.emplace_back(clickRecognizer_);
135         }
136         break;
137     }
138 }
139 
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)140 void ScrollableActuator::InitClickRecognizer(const OffsetF& coordinateOffset,
141     const GetEventTargetImpl& getEventTargetImpl, const RefPtr<FrameNode>& frameNode,
142     const RefPtr<TargetComponent>& targetComponent, const RefPtr<ScrollableEvent>& event, bool clickJudge,
143     const PointF& localPoint, SourceType source)
144 {
145     if (!clickRecognizer_) {
146         clickRecognizer_ = MakeRefPtr<ClickRecognizer>();
147     }
148     bool isHitTestBlock = event->IsHitTestBlock(localPoint, source);
149     clickRecognizer_->SetCoordinateOffset(Offset(coordinateOffset.GetX(), coordinateOffset.GetY()));
150     clickRecognizer_->SetGetEventTargetImpl(getEventTargetImpl);
151     clickRecognizer_->SetNodeId(frameNode->GetId());
152     clickRecognizer_->AttachFrameNode(frameNode);
153     clickRecognizer_->SetTargetComponent(targetComponent);
154     clickRecognizer_->SetIsSystemGesture(true);
155     clickRecognizer_->SetRecognizerType(GestureTypeName::TAP_GESTURE);
156     clickRecognizer_->SetSysGestureJudge([isHitTestBlock, clickJudge](const RefPtr<GestureInfo>& gestureInfo,
157                                              const std::shared_ptr<BaseGestureEvent>&) -> GestureJudgeResult {
158         TAG_LOGI(
159             AceLogTag::ACE_SCROLLABLE, "Scrollable GestureJudge:%{public}d, %{public}d", isHitTestBlock, clickJudge);
160         return isHitTestBlock || clickJudge ? GestureJudgeResult::CONTINUE : GestureJudgeResult::REJECT;
161     });
162     clickRecognizer_->SetOnClick([weak = WeakClaim(RawPtr(frameNode))](const ClickInfo&) {
163         auto frameNode = weak.Upgrade();
164         CHECK_NULL_VOID(frameNode);
165         auto pattern = frameNode->GetPattern<ListPattern>();
166         CHECK_NULL_VOID(pattern);
167         auto item = pattern->GetSwiperItem().Upgrade();
168         CHECK_NULL_VOID(item);
169         item->ResetSwipeStatus();
170     });
171 }
172 
173 namespace {
GetOverrideRecognizer(const RefPtr<FrameNode> & frameNode)174 RefPtr<NGGestureRecognizer> GetOverrideRecognizer(const RefPtr<FrameNode>& frameNode)
175 {
176     auto scroll = frameNode->GetPattern<ScrollPattern>();
177     CHECK_NULL_RETURN(scroll, nullptr);
178     return scroll->GetOverrideRecognizer();
179 }
180 } // namespace
181 
CollectScrollableTouchTarget(const OffsetF & coordinateOffset,const GetEventTargetImpl & getEventTargetImpl,TouchTestResult & result,const RefPtr<FrameNode> & frameNode,const RefPtr<TargetComponent> & targetComponent,ResponseLinkResult & responseLinkResult,int32_t touchId)182 void ScrollableEvent::CollectScrollableTouchTarget(const OffsetF& coordinateOffset,
183     const GetEventTargetImpl& getEventTargetImpl, TouchTestResult& result, const RefPtr<FrameNode>& frameNode,
184     const RefPtr<TargetComponent>& targetComponent, ResponseLinkResult& responseLinkResult, int32_t touchId)
185 {
186     if (auto superRecognizer = GetOverrideRecognizer(frameNode)) {
187         result.emplace_back(superRecognizer);
188         auto recognizerGroup = AceType::DynamicCast<RecognizerGroup>(superRecognizer);
189         if (recognizerGroup) {
190             auto offset = Offset(coordinateOffset.GetX(), coordinateOffset.GetY());
191             recognizerGroup->SetRecognizerInfoRecursively(offset, frameNode, targetComponent, getEventTargetImpl);
192             recognizerGroup->CollectResponseLinkRecognizersRecursively(responseLinkResult);
193             recognizerGroup->BeginReferee(touchId, true);
194         } else {
195             responseLinkResult.emplace_back(superRecognizer);
196         }
197         superRecognizer->SetNodeId(frameNode->GetId());
198         superRecognizer->AttachFrameNode(frameNode);
199         superRecognizer->SetTargetComponent(targetComponent);
200         superRecognizer->SetIsSystemGesture(true);
201         superRecognizer->SetCoordinateOffset(Offset(coordinateOffset.GetX(), coordinateOffset.GetY()));
202         superRecognizer->SetGetEventTargetImpl(getEventTargetImpl);
203         return;
204     }
205     if (scrollable_) {
206         scrollable_->SetGetEventTargetImpl(getEventTargetImpl);
207         scrollable_->SetCoordinateOffset(Offset(coordinateOffset.GetX(), coordinateOffset.GetY()));
208         scrollable_->OnCollectTouchTarget(result, frameNode, targetComponent, responseLinkResult);
209     }
210 }
211 } // namespace OHOS::Ace::NG
212