• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLL_SCROLL_PATTERN_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLL_SCROLL_PATTERN_H
18 
19 #include "base/geometry/axis.h"
20 #include "core/components/common/layout/constants.h"
21 #include "core/components_ng/pattern/scroll/scroll_accessibility_property.h"
22 #include "core/components_ng/pattern/scroll/scroll_edge_effect.h"
23 #include "core/components_ng/pattern/scroll/scroll_event_hub.h"
24 #include "core/components_ng/pattern/scroll/scroll_layout_algorithm.h"
25 #include "core/components_ng/pattern/scroll/scroll_layout_property.h"
26 #include "core/components_ng/pattern/scroll/scroll_paint_method.h"
27 #include "core/components_ng/pattern/scroll_bar/proxy/scroll_bar_proxy.h"
28 #include "core/components_ng/pattern/scrollable/scrollable_pattern.h"
29 #include "core/components_ng/pattern/scrollable/scrollable_properties.h"
30 
31 namespace OHOS::Ace::NG {
32 class InspectorFilter;
33 
34 class ScrollPattern : public ScrollablePattern {
35     DECLARE_ACE_TYPE(ScrollPattern, ScrollablePattern);
36 
37 public:
ScrollPattern()38     ScrollPattern() : ScrollablePattern(EdgeEffect::NONE, true) {}
39 
40     ~ScrollPattern() override = default;
41 
UsResRegion()42     bool UsResRegion() override
43     {
44         return false;
45     }
46 
CreateLayoutProperty()47     RefPtr<LayoutProperty> CreateLayoutProperty() override
48     {
49         return MakeRefPtr<ScrollLayoutProperty>();
50     }
51 
CreateAccessibilityProperty()52     RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override
53     {
54         return MakeRefPtr<ScrollAccessibilityProperty>();
55     }
56 
CreateLayoutAlgorithm()57     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override
58     {
59         auto layoutAlgorithm = MakeRefPtr<ScrollLayoutAlgorithm>(currentOffset_);
60         return layoutAlgorithm;
61     }
62 
CreateNodePaintMethod()63     RefPtr<NodePaintMethod> CreateNodePaintMethod() override
64     {
65         auto paint = MakeRefPtr<ScrollPaintMethod>();
66         paint->SetScrollBar(GetScrollBar());
67         CreateScrollBarOverlayModifier();
68         paint->SetScrollBarOverlayModifier(GetScrollBarOverlayModifier());
69         auto scrollEffect = GetScrollEdgeEffect();
70         if (scrollEffect && scrollEffect->IsFadeEffect()) {
71             paint->SetEdgeEffect(scrollEffect);
72         }
73         return paint;
74     }
75 
OpIncType()76     OPINC_TYPE_E OpIncType() override
77     {
78         return OPINC_PARENT_POSSIBLE;
79     }
80 
CreateEventHub()81     RefPtr<EventHub> CreateEventHub() override
82     {
83         return MakeRefPtr<ScrollEventHub>();
84     }
85 
IsScrollable()86     bool IsScrollable() const override
87     {
88         return GetAxis() != Axis::NONE;
89     }
90 
IsPositiveScrollableDistance()91     bool IsPositiveScrollableDistance()
92     {
93         return Positive(scrollableDistance_);
94     }
95 
96     bool OnScrollCallback(float offset, int32_t source) override;
97 
98     void OnScrollEndCallback() override;
99 
GetCurrentPosition()100     double GetCurrentPosition() const
101     {
102         return currentOffset_;
103     }
104 
GetTotalOffset()105     float GetTotalOffset() const override
106     {
107         return -currentOffset_;
108     }
109 
110     void ResetPosition();
111 
GetCurrentOffset()112     Offset GetCurrentOffset() const
113     {
114         if (GetAxis() == Axis::HORIZONTAL) {
115             return Offset{currentOffset_, 0};
116         }
117         return Offset{0, currentOffset_};
118     }
119 
GetScrollableDistance()120     float GetScrollableDistance() const
121     {
122         return scrollableDistance_;
123     }
124 
IsRowReverse()125     bool IsRowReverse() const
126     {
127         return direction_ == FlexDirection::ROW_REVERSE;
128     }
129 
IsColReverse()130     bool IsColReverse() const
131     {
132         return  direction_ == FlexDirection::COLUMN_REVERSE;
133     }
134 
GetScrollPositionController()135     RefPtr<ScrollableController> GetScrollPositionController() const
136     {
137         return positionController_;
138     }
139 
SetDirection(FlexDirection direction)140     void SetDirection(FlexDirection direction)
141     {
142         direction_ = direction;
143     }
144 
GetFocusPattern()145     FocusPattern GetFocusPattern() const override
146     {
147         return { FocusType::SCOPE, true };
148     }
149 
150     bool ScrollToNode(const RefPtr<FrameNode>& focusFrameNode) override;
151     std::pair<std::function<bool(float)>, Axis> GetScrollOffsetAbility() override;
152 
153     bool IsAtTop() const override;
154     bool IsAtBottom() const override;
155     bool IsOutOfBoundary(bool useCurrentDelta = true) override;
156     OverScrollOffset GetOverScrollOffset(double delta) const override;
157 
158     void OnAnimateStop() override;
159     bool UpdateCurrentOffset(float offset, int32_t source) override;
160     void ScrollToEdge(ScrollEdgeType scrollEdgeType, bool smooth) override;
161 
162     void CheckScrollToEdge();
163 
GetScrollEdgeType()164     ScrollEdgeType GetScrollEdgeType() const override
165     {
166         return scrollEdgeType_;
167     }
168 
SetScrollEdgeType(ScrollEdgeType scrollEdgeType)169     void SetScrollEdgeType(ScrollEdgeType scrollEdgeType) override
170     {
171         scrollEdgeType_ = scrollEdgeType;
172     }
173 
174     void ScrollBy(float pixelX, float pixelY, bool smooth, const std::function<void()>& onFinish = nullptr);
175     bool ScrollPage(bool reverse, bool smooth,
176         AccessibilityScrollType scrollType = AccessibilityScrollType::SCROLL_FULL,
177         const std::function<void()>& onFinish = nullptr);
178     void ScrollTo(float position) override;
179     void JumpToPosition(float position, int32_t source = SCROLL_FROM_JUMP);
GetMainContentSize()180     float GetMainContentSize() const override
181     {
182         return viewPortLength_;
183     }
SupportScrollToIndex()184     bool SupportScrollToIndex() const override
185     {
186         return false;
187     }
188     bool ScrollPageCheck(float delta, int32_t source);
189     void AdjustOffset(float& delta, int32_t source);
190     Rect GetItemRect(int32_t index) const override;
191 
192     // scrollSnap
193     std::optional<float> CalePredictSnapOffset(float delta, float dragDistance = 0.f, float velocity = 0.f) override;
194     bool NeedScrollSnapToSide(float delta) override;
195     void CaleSnapOffsets();
196     void CaleSnapOffsetsByInterval(ScrollSnapAlign scrollSnapAlign);
197     void CaleSnapOffsetsByPaginations(ScrollSnapAlign scrollSnapAlign);
198 
199     float GetSelectScrollWidth();
200 
IsSnapToInterval()201     bool IsSnapToInterval() const
202     {
203         return snapPaginations_.empty();
204     }
205 
GetSnapOffsets()206     std::vector<float> GetSnapOffsets() const
207     {
208         return snapOffsets_;
209     }
210 
SetSnapOffsets(const std::vector<float> & snapOffset)211     void SetSnapOffsets(const std::vector<float>& snapOffset)
212     {
213         snapOffsets_ = snapOffset;
214     }
215 
SetIntervalSize(const Dimension & intervalSize)216     void SetIntervalSize(const Dimension& intervalSize)
217     {
218         if (intervalSize_ != intervalSize) {
219             intervalSize_ = intervalSize;
220             scrollSnapUpdate_ = true;
221         }
222     }
223 
GetIntervalSize()224     Dimension GetIntervalSize() const
225     {
226         return intervalSize_;
227     }
228 
SetSnapPaginations(const std::vector<Dimension> & snapPaginations)229     void SetSnapPaginations(const std::vector<Dimension>& snapPaginations)
230     {
231         if (snapPaginations_ != snapPaginations) {
232             snapPaginations_ = snapPaginations;
233             scrollSnapUpdate_ = true;
234         }
235     }
236 
GetSnapPaginations()237     std::vector<Dimension> GetSnapPaginations() const
238     {
239         return snapPaginations_;
240     }
241 
SetEnableSnapToSide(const std::pair<bool,bool> & enableSnapToSide)242     void SetEnableSnapToSide(const std::pair<bool, bool>& enableSnapToSide)
243     {
244         enableSnapToSide_ = enableSnapToSide;
245     }
246 
GetEnableSnapToSide()247     std::pair<bool, bool> GetEnableSnapToSide() const
248     {
249         return enableSnapToSide_;
250     }
251 
SetScrollSnapUpdate(bool scrollSnapUpdate)252     void SetScrollSnapUpdate(bool scrollSnapUpdate)
253     {
254         scrollSnapUpdate_ = scrollSnapUpdate;
255     }
256 
GetScrollSnapUpdate()257     bool GetScrollSnapUpdate() const
258     {
259         return scrollSnapUpdate_;
260     }
261 
GetScrollSnapAlign()262     ScrollSnapAlign GetScrollSnapAlign() const
263     {
264         auto host = GetHost();
265         CHECK_NULL_RETURN(host, ScrollSnapAlign::NONE);
266         auto scrollLayoutProperty = host->GetLayoutProperty<ScrollLayoutProperty>();
267         CHECK_NULL_RETURN(scrollLayoutProperty, ScrollSnapAlign::NONE);
268         return scrollLayoutProperty->GetScrollSnapAlign().value_or(ScrollSnapAlign::NONE);
269     }
270 
271     std::string ProvideRestoreInfo() override;
272     void OnRestoreInfo(const std::string& restoreInfo) override;
273 
SetIsWidthModifiedBySelect(bool isModified)274     void SetIsWidthModifiedBySelect(bool isModified)
275     {
276         isWidthModifiedBySelect_ = isModified;
277     }
278 
IsWidthModifiedBySelect()279     bool IsWidthModifiedBySelect() const
280     {
281         return isWidthModifiedBySelect_;
282     }
283 
SetIsSelectScroll(bool isSelect)284     void SetIsSelectScroll(bool isSelect)
285     {
286         isSelectScroll_ = isSelect;
287     }
288 
IsSelectScroll()289     bool IsSelectScroll() const
290     {
291         return isSelectScroll_;
292     }
293 
SetHasOptionWidth(bool hasOptionWidth)294     void SetHasOptionWidth(bool hasOptionWidth)
295     {
296         hasOptionWidth_ = hasOptionWidth;
297     }
298 
GetHasOptionWidth()299     bool GetHasOptionWidth()
300     {
301         return hasOptionWidth_;
302     }
303 
SetEnablePaging(ScrollPagingStatus status)304     void SetEnablePaging(ScrollPagingStatus status)
305     {
306         enablePagingStatus_ =  status;
307     }
308 
GetEnablePaging()309     ScrollPagingStatus GetEnablePaging()
310     {
311         return enablePagingStatus_;
312     }
313 
IsScrollSnap()314     bool IsScrollSnap() override
315     {
316         return !snapOffsets_.empty() &&
317                (GetScrollSnapAlign() != ScrollSnapAlign::NONE || enablePagingStatus_ == ScrollPagingStatus::VALID);
318     }
319 
320     void TriggerModifyDone();
321 
SetInitialOffset(const OffsetT<CalcDimension> & offset)322     void SetInitialOffset(const OffsetT<CalcDimension>& offset)
323     {
324         initialOffset_ = offset;
325     }
326 
GetInitialOffset()327     OffsetT<CalcDimension> GetInitialOffset() const
328     {
329         return initialOffset_.has_value() ? initialOffset_.value() : OffsetT(CalcDimension(), CalcDimension());
330     }
331 
NeedSetInitialOffset()332     bool NeedSetInitialOffset()
333     {
334         return !isInitialized_ && initialOffset_.has_value();
335     }
336 
337     void AddScrollMeasureInfo(const std::optional<LayoutConstraintF>& parentConstraint,
338         const std::optional<LayoutConstraintF>& childConstraint, const SizeF& selfSize, const SizeF& childSize);
339 
340     void AddScrollLayoutInfo();
341 
342     void GetScrollSnapAlignDumpInfo();
343 
344     void GetScrollPagingStatusDumpInfo();
345 
346     void DumpAdvanceInfo() override;
347 
GetViewSize()348     SizeF GetViewSize() const
349     {
350         return viewSize_;
351     }
352 
GetViewPortExtent()353     SizeF GetViewPortExtent() const
354     {
355         return viewPortExtent_;
356     }
357 
358     void ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const override;
359 
360     bool OnScrollSnapCallback(double targetOffset, double velocity) override;
361 
362 protected:
363     void DoJump(float position, int32_t source = SCROLL_FROM_JUMP);
364 
365 private:
366     void OnModifyDone() override;
367     bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override;
368 
369     bool IsCrashTop() const;
370     bool IsCrashBottom() const;
371     bool ReachStart(bool firstLayout) const;
372     bool ReachEnd(bool firstLayout) const;
373     bool IsScrollOutOnEdge(float delta) const;
374     void HandleCrashTop();
375     void HandleCrashBottom();
IsEnablePagingValid()376     bool IsEnablePagingValid() const
377     {
378         return enablePagingStatus_ == ScrollPagingStatus::VALID && GetScrollSnapAlign() == ScrollSnapAlign::NONE;
379     }
380 
381     void RegisterScrollBarEventTask();
382     void HandleScrollEffect();
383     void ValidateOffset(int32_t source);
384     float ValidateOffset(int32_t source, float willScrollOffset);
385     void HandleScrollPosition(float scroll);
386     float FireTwoDimensionOnWillScroll(float scroll);
387     void FireOnDidScroll(float scroll);
388     void FireOnReachStart(const OnReachEvent& onReachStart) override;
389     void FireOnReachEnd(const OnReachEvent& onReachEnd) override;
390     void SetEdgeEffectCallback(const RefPtr<ScrollEdgeEffect>& scrollEffect) override;
391     void UpdateScrollBarOffset() override;
392     void SetAccessibilityAction() override;
393     bool ScrollSnapTrigger();
394     void CheckScrollable();
395     OffsetF GetOffsetToScroll(const RefPtr<FrameNode>& childFrame) const;
396     bool SetScrollProperties(const RefPtr<LayoutWrapper>& dirty);
397     std::string GetScrollSnapPagination() const;
398 
399     float currentOffset_ = 0.0f;
400     float lastOffset_ = 0.0f;
401     // keep lastOffset_ for compatibility, use prevOffset_ for onReachStart/onReachEnd
402     float prevOffset_ = 0.0f;
403     float scrollableDistance_ = 0.0f;
404     float viewPortLength_ = 0.0f;
405     SizeF viewPort_;
406     SizeF viewSize_;
407     SizeF viewPortExtent_;
408     FlexDirection direction_ { FlexDirection::COLUMN };
409 
410     // scrollSnap
411     std::vector<float> snapOffsets_;
412     std::vector<Dimension> snapPaginations_;
413     std::pair<bool, bool> enableSnapToSide_ = { true, true };
414     Dimension intervalSize_;
415     bool scrollSnapUpdate_ = false;
416 
417     bool isWidthModifiedBySelect_ = false;
418     bool isSelectScroll_ = false;
419     bool hasOptionWidth_ = false;
420 
421     // enablePaging
422     ScrollPagingStatus enablePagingStatus_ = ScrollPagingStatus::NONE;
423     float lastPageLength_ = 0.0f;
424     float GetPagingOffset(float delta, float dragDistance, float velocity)  const;
425     float GetPagingDelta(float dragDistance, float velocity, float pageLength) const;
426 
427     //initialOffset
428     std::optional<OffsetT<CalcDimension>> initialOffset_;
429 
430     //scrollToEdge
431     ScrollEdgeType scrollEdgeType_ = ScrollEdgeType::SCROLL_NONE;
432 
433     // dump info
434     std::list<ScrollLayoutInfo> scrollLayoutInfos_;
435     std::list<ScrollMeasureInfo> scrollMeasureInfos_;
436 };
437 
438 } // namespace OHOS::Ace::NG
439 
440 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SCROLL_SCROLL_PATTERN_H
441