• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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_GRID_GRID_PATTERN_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_GRID_GRID_PATTERN_H
18 
19 #include "core/components_ng/pattern/grid/grid_accessibility_property.h"
20 #include "core/components_ng/pattern/grid/grid_event_hub.h"
21 #include "core/components_ng/pattern/grid/grid_layout_info.h"
22 #include "core/components_ng/pattern/grid/grid_layout_property.h"
23 #include "core/components_ng/pattern/grid/grid_paint_method.h"
24 #include "core/components_ng/pattern/scrollable/scrollable_pattern.h"
25 
26 namespace OHOS::Ace::NG {
27 class InspectorFilter;
28 
29 struct GridItemIndexInfo {
30     int32_t mainIndex = -1;
31     int32_t crossIndex = -1;
32     int32_t mainSpan = -1;
33     int32_t crossSpan = -1;
34     int32_t mainStart = -1;
35     int32_t mainEnd = -1;
36     int32_t crossStart = -1;
37     int32_t crossEnd = -1;
38 };
39 
40 class ACE_EXPORT GridPattern : public ScrollablePattern {
41     DECLARE_ACE_TYPE(GridPattern, ScrollablePattern);
42 
43 public:
44     GridPattern() = default;
45 
CreateLayoutProperty()46     RefPtr<LayoutProperty> CreateLayoutProperty() override
47     {
48         return MakeRefPtr<GridLayoutProperty>();
49     }
50 
51     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override;
52 
53     void BeforeCreateLayoutWrapper() override;
54 
55     RefPtr<NodePaintMethod> CreateNodePaintMethod() override;
56 
CreateAccessibilityProperty()57     RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override
58     {
59         return MakeRefPtr<GridAccessibilityProperty>();
60     }
61 
IsScrollable()62     bool IsScrollable() const override
63     {
64         return isConfigScrollable_;
65     }
66 
67     DisplayMode GetDefaultScrollBarDisplayMode() const override;
68 
SetMultiSelectable(bool multiSelectable)69     void SetMultiSelectable(bool multiSelectable)
70     {
71         multiSelectable_ = multiSelectable;
72     }
73 
MultiSelectable()74     bool MultiSelectable() const
75     {
76         return multiSelectable_;
77     }
78 
SetSupportAnimation(bool supportAnimation)79     void SetSupportAnimation(bool supportAnimation)
80     {
81         supportAnimation_ = supportAnimation;
82     }
83 
SupportAnimation()84     bool SupportAnimation() const
85     {
86         return supportAnimation_;
87     }
88 
GetFocusPattern()89     FocusPattern GetFocusPattern() const override
90     {
91         return { FocusType::SCOPE, true };
92     }
93 
GetScopeFocusAlgorithm()94     ScopeFocusAlgorithm GetScopeFocusAlgorithm() override
95     {
96         auto property = GetLayoutProperty<GridLayoutProperty>();
97         if (!property) {
98             return ScopeFocusAlgorithm();
99         }
100         return ScopeFocusAlgorithm(property->IsVertical(), true, ScopeType::OTHERS,
101             [wp = WeakClaim(this)](
102                 FocusStep step, const WeakPtr<FocusHub>& currFocusNode, WeakPtr<FocusHub>& nextFocusNode) {
103                 auto grid = wp.Upgrade();
104                 if (grid) {
105                     nextFocusNode = grid->GetNextFocusNode(step, currFocusNode);
106                 }
107             });
108     }
109 
110     int32_t GetFocusNodeIndex(const RefPtr<FocusHub>& focusNode) override;
111 
112     void ScrollToFocusNodeIndex(int32_t index) override;
113 
114     std::pair<std::function<bool(float)>, Axis> GetScrollOffsetAbility() override;
115 
116     std::function<bool(int32_t)> GetScrollIndexAbility() override;
117 
118     bool ScrollToNode(const RefPtr<FrameNode>& focusFrameNode) override;
119 
CreateEventHub()120     RefPtr<EventHub> CreateEventHub() override
121     {
122         return MakeRefPtr<GridEventHub>();
123     }
124 
UsResRegion()125     bool UsResRegion() override
126     {
127         return false;
128     }
129 
GetGridLayoutInfo()130     const GridLayoutInfo& GetGridLayoutInfo() const
131     {
132         return gridLayoutInfo_;
133     }
134 
135     /* caution when using mutable reference */
GetMutableLayoutInfo()136     GridLayoutInfo& GetMutableLayoutInfo()
137     {
138         return gridLayoutInfo_;
139     }
140 
ResetGridLayoutInfo()141     void ResetGridLayoutInfo()
142     {
143         gridLayoutInfo_.lineHeightMap_.clear();
144         gridLayoutInfo_.gridMatrix_.clear();
145         gridLayoutInfo_.endIndex_ = gridLayoutInfo_.startIndex_ - 1;
146         gridLayoutInfo_.endMainLineIndex_ = 0;
147         gridLayoutInfo_.ResetPositionFlags();
148         gridLayoutInfo_.irregularItemsPosition_.clear();
149         gridLayoutInfo_.clearStretch_ = true;
150     }
151 
SetIrregular(bool value)152     void SetIrregular(bool value)
153     {
154         irregular_ = value;
155     }
156 
ResetPositionFlags()157     void ResetPositionFlags()
158     {
159         gridLayoutInfo_.ResetPositionFlags();
160     }
161 
162     void ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const override;
163 
164     bool UpdateCurrentOffset(float offset, int32_t source) override;
165 
IsAtTop()166     bool IsAtTop() const override
167     {
168         return gridLayoutInfo_.reachStart_;
169     }
170 
IsAtBottom()171     bool IsAtBottom() const override
172     {
173         return gridLayoutInfo_.offsetEnd_;
174     }
175 
176     OverScrollOffset GetOverScrollOffset(double delta) const override;
177     void GetEndOverScrollIrregular(OverScrollOffset& offset, float delta) const;
178 
179     void ScrollPage(bool reverse, AccessibilityScrollType scrollType = AccessibilityScrollType::SCROLL_FULL);
180 
181     bool UpdateStartIndex(int32_t index);
182 
183     bool UpdateStartIndex(int32_t index, ScrollAlign align);
184 
GetTotalOffset()185     float GetTotalOffset() const override
186     {
187         return EstimateHeight();
188     }
189 
190     float GetTotalHeight() const override;
191 
192     void OnAnimateStop() override;
193 
194     void AnimateTo(
195         float position, float duration, const RefPtr<Curve>& curve, bool smooth, bool canOverScroll = false,
196         bool useTotalOffset = true) override;
197     void ScrollTo(float position) override;
198 
199     void ScrollBy(float offset);
200 
GetDefaultScrollAlign()201     ScrollAlign GetDefaultScrollAlign() const override
202     {
203         return ScrollAlign::AUTO;
204     }
205 
206     void ScrollToEdge(ScrollEdgeType scrollEdgeType, bool smooth) override;
207 
208     void ScrollToIndex(int32_t index, bool smooth = false, ScrollAlign align = ScrollAlign::AUTO,
209         std::optional<float> extraOffset = std::nullopt) override;
210     void AnimateToTarget(ScrollAlign align, const RefPtr<LayoutAlgorithmWrapper>& algo);
211     bool AnimateToTargetImpl(ScrollAlign align, const RefPtr<LayoutAlgorithmWrapper>& algo);
212 
213     int32_t GetOriginalIndex() const;
214     int32_t GetCrossCount() const;
215     int32_t GetChildrenCount() const;
216     void MoveItems(int32_t itemIndex, int32_t insertIndex);
217     void ClearDragState();
218     float EstimateHeight() const;
219     float GetAverageHeight() const;
220 
221     void DumpAdvanceInfo() override;
222 
223     std::string ProvideRestoreInfo() override;
224     void OnRestoreInfo(const std::string& restoreInfo) override;
225     Rect GetItemRect(int32_t index) const override;
226 
IsNeedInitClickEventRecorder()227     bool IsNeedInitClickEventRecorder() const override
228     {
229         return true;
230     }
231 
GetPreloadItemList()232     const std::list<GridPreloadItem>& GetPreloadItemList() const
233     {
234         return preloadItemList_;
235     }
236 
SetPreloadItemList(std::list<GridPreloadItem> && list)237     void SetPreloadItemList(std::list<GridPreloadItem>&& list)
238     {
239         preloadItemList_ = std::move(list);
240     }
241 
242     std::vector<RefPtr<FrameNode>> GetVisibleSelectedItems() override;
243 
244     void StopAnimate() override;
245 
246     bool IsPredictOutOfRange(int32_t index) const;
247 
248     bool IsReverse() const override;
249 
GetAxis()250     Axis GetAxis() const override
251     {
252         return gridLayoutInfo_.axis_;
253     }
254 
GetDefaultCachedCount()255     int32_t GetDefaultCachedCount() const
256     {
257         return gridLayoutInfo_.defCachedCount_;
258     }
259 
260 private:
261     /**
262      * @brief calculate where startMainLine_ should be after spring animation.
263      * @return main axis position relative to viewport, positive when below viewport.
264      */
265     float GetEndOffset();
266     float GetMainGap() const;
267     float GetAllDelta();
268     void CheckScrollable();
269     bool IsOutOfBoundary(bool useCurrentDelta) override;
270     void SetEdgeEffectCallback(const RefPtr<ScrollEdgeEffect>& scrollEffect) override;
271     SizeF GetContentSize() const;
272     void OnModifyDone() override;
273     bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override;
274     WeakPtr<FocusHub> GetNextFocusNode(FocusStep step, const WeakPtr<FocusHub>& currentFocusNode);
275     std::pair<int32_t, int32_t> GetNextIndexByStep(
276         int32_t curMainIndex, int32_t curCrossIndex, int32_t curMainSpan, int32_t curCrossSpan, FocusStep step);
277     WeakPtr<FocusHub> SearchFocusableChildInCross(int32_t tarMainIndex, int32_t tarCrossIndex, int32_t maxCrossCount,
278         int32_t curMainIndex = -1, int32_t curCrossIndex = -1);
279     WeakPtr<FocusHub> SearchIrregularFocusableChild(int32_t tarMainIndex, int32_t tarCrossIndex);
280     WeakPtr<FocusHub> GetChildFocusNodeByIndex(int32_t tarMainIndex, int32_t tarCrossIndex, int32_t tarIndex = -1);
281     std::unordered_set<int32_t> GetFocusableChildCrossIndexesAt(int32_t tarMainIndex);
282     void ScrollToFocusNode(const WeakPtr<FocusHub>& focusNode);
283     void FlushFocusOnScroll(const GridLayoutInfo& gridLayoutInfo);
284     std::pair<bool, bool> IsFirstOrLastFocusableChild(int32_t curMainIndex, int32_t curCrossIndex);
285     std::pair<FocusStep, FocusStep> GetFocusSteps(int32_t curMainIndex, int32_t curCrossIndex, FocusStep step);
286     void InitOnKeyEvent(const RefPtr<FocusHub>& focusHub);
287     bool OnKeyEvent(const KeyEvent& event);
288     bool HandleDirectionKey(KeyCode code);
289 
290     void ClearMultiSelect() override;
291     bool IsItemSelected(const GestureEvent& info) override;
292     void MultiSelectWithoutKeyboard(const RectF& selectedZone) override;
293     void UpdateScrollBarOffset() override;
294     void UpdateRectOfDraggedInItem(int32_t insertIndex);
295 
296     void ProcessEvent(bool indexChanged, float finalOffset);
297     void MarkDirtyNodeSelf();
298     void OnScrollEndCallback() override;
299 
300     /**
301      * @brief preform a layout if LayoutInfo is out of sync before calculating spring positions.
302      * INVARIANT: overScroll always enabled in the scope of this function. Because this function only runs in the
303      * context of spring animation.
304      */
305     void SyncLayoutBeforeSpring();
306 
307     void FireOnScrollStart() override;
308     void FireOnReachStart(const OnReachEvent& onReachStart) override;
309     void FireOnReachEnd(const OnReachEvent& onReachEnd) override;
310     void FireOnScrollIndex(bool indexChanged, const ScrollIndexFunc& onScrollIndex);
311 
312     inline bool UseIrregularLayout() const;
313 
314     int32_t CalcIntersectAreaInTargetDirectionShadow(GridItemIndexInfo itemIndexInfo, bool isFindInMainAxis);
315     double GetNearestDistanceFromChildToCurFocusItemInMainAxis(int32_t targetIndex, GridItemIndexInfo itemIndexInfo);
316     double GetNearestDistanceFromChildToCurFocusItemInCrossAxis(int32_t targetIndex, GridItemIndexInfo itemIndexInfo);
317     void ResetAllDirectionsStep();
318 
319     std::string GetIrregularIndexesString() const;
320 
321     bool supportAnimation_ = false;
322     bool isConfigScrollable_ = false;
323 
324     bool scrollable_ = true;
325     bool forceOverScroll_ = false;
326 
327     float endHeight_ = 0.0f;
328     bool isLeftStep_ = false;
329     bool isRightStep_ = false;
330     bool isUpStep_ = false;
331     bool isDownStep_ = false;
332     bool isLeftEndStep_ = false;
333     bool isRightEndStep_ = false;
334     bool isSmoothScrolling_ = false;
335     bool irregular_ = false; // true if LayoutOptions require running IrregularLayout
336 
337     ScrollAlign scrollAlign_ = ScrollAlign::AUTO;
338     std::optional<int32_t> targetIndex_;
339     std::pair<std::optional<float>, std::optional<float>> scrollbarInfo_;
340     GridItemIndexInfo curFocusIndexInfo_;
341     GridLayoutInfo scrollGridLayoutInfo_;
342     GridLayoutInfo gridLayoutInfo_;
343     std::list<GridPreloadItem> preloadItemList_; // list of GridItems to build preemptively in IdleTask
344     ACE_DISALLOW_COPY_AND_MOVE(GridPattern);
345 };
346 
347 } // namespace OHOS::Ace::NG
348 
349 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_GRID_GRID_PATTERN_H
350