• 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_LIST_LIST_ITEM_GROUP_PATTERN_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_ITEM_GROUP_PATTERN_H
18 
19 #include "base/memory/referenced.h"
20 #include "base/utils/noncopyable.h"
21 #include "base/utils/utils.h"
22 #include "core/components_ng/pattern/list/list_item_group_accessibility_property.h"
23 #include "core/components_ng/pattern/list/list_children_main_size.h"
24 #include "core/components_ng/pattern/list/list_item_group_layout_algorithm.h"
25 #include "core/components_ng/pattern/list/list_item_group_layout_property.h"
26 #include "core/components_ng/pattern/list/list_layout_property.h"
27 #include "core/components_ng/pattern/list/list_position_map.h"
28 #include "core/components_ng/pattern/pattern.h"
29 #include "core/components_ng/syntax/shallow_builder.h"
30 
31 namespace OHOS::Ace::NG {
32 
33 struct ListItemGroupPaintInfo {
34     TextDirection layoutDirection = TextDirection::LTR;
35     float mainSize = 0.0f;
36     bool vertical = false;
37     int32_t lanes = 1;
38     float spaceWidth = 0.0f;
39     float laneGutter = 0.0f;
40     int32_t totalItemCount = 0;
41     float listContentSize = FLT_MAX;
42 };
43 
44 enum ListItemGroupArea {
45     NONE_AREA,
46     IN_LIST_ITEM_AREA,
47     IN_HEADER_AREA,
48     IN_FOOTER_AREA
49 };
50 
51 struct VisibleContentInfo {
52     int32_t area = -1;
53     int32_t indexInGroup = -1;
54 };
55 
56 struct ListMainSizeValues {
57     float startPos = 0.0f;
58     float endPos = 0.0f;
59     std::optional<int32_t> jumpIndexInGroup;
60     float prevContentMainSize = 0.0f;
61     ScrollAlign scrollAlign = ScrollAlign::START;
62     std::optional<float> layoutStartMainPos;
63     std::optional<float> layoutEndMainPos;
64     float referencePos = 0.0f;
65     float contentStartOffset = 0.0f;
66     float contentEndOffset = 0.0f;
67     bool forward = true;
68     bool backward = false;
69 };
70 
71 class ACE_EXPORT ListItemGroupPattern : public Pattern {
72     DECLARE_ACE_TYPE(ListItemGroupPattern, Pattern);
73 
74 public:
ListItemGroupPattern(const RefPtr<ShallowBuilder> & shallowBuilder,V2::ListItemGroupStyle listItemGroupStyle)75     explicit ListItemGroupPattern(
76         const RefPtr<ShallowBuilder>& shallowBuilder, V2::ListItemGroupStyle listItemGroupStyle)
77         : shallowBuilder_(shallowBuilder), listItemGroupStyle_(listItemGroupStyle)
78     {}
79     ~ListItemGroupPattern() override = default;
80 
81     void DumpAdvanceInfo() override;
82     void DumpAdvanceInfo(std::unique_ptr<JsonValue>& json) override;
IsAtomicNode()83     bool IsAtomicNode() const override
84     {
85         return false;
86     }
87 
GetFocusPattern()88     FocusPattern GetFocusPattern() const override
89     {
90         return { FocusType::SCOPE, true };
91     }
92 
93     ScopeFocusAlgorithm GetScopeFocusAlgorithm() override;
94 
95     bool FindHeadOrTailChild(const RefPtr<FocusHub>& groupFocus, FocusStep step, WeakPtr<FocusHub>& target);
96 
97     WeakPtr<FocusHub> GetChildFocusNodeByIndex(int32_t tarIndexInGroup);
98 
99     WeakPtr<FocusHub> GetNextFocusNode(FocusStep step, const WeakPtr<FocusHub>& currentFocusNode);
100 
101     void NotifyDataChange(int32_t index, int32_t count) override;
102 
CreateLayoutProperty()103     RefPtr<LayoutProperty> CreateLayoutProperty() override
104     {
105         return MakeRefPtr<ListItemGroupLayoutProperty>();
106     }
107 
CreateAccessibilityProperty()108     RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override
109     {
110         return MakeRefPtr<ListItemGroupAccessibilityProperty>();
111     }
112 
113     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override;
114 
115     RefPtr<NodePaintMethod> CreateNodePaintMethod() override;
116 
OnAttachAdapter(const RefPtr<FrameNode> & node,const RefPtr<UINode> & child)117     bool OnAttachAdapter(const RefPtr<FrameNode>& node, const RefPtr<UINode>& child) override
118     {
119         node->AddChild(child);
120         return true;
121     }
122 
AddHeader(const RefPtr<NG::UINode> & header)123     void AddHeader(const RefPtr<NG::UINode>& header)
124     {
125         auto host = GetHost();
126         CHECK_NULL_VOID(host);
127         auto prevHeader = header_.Upgrade();
128         if (!prevHeader) {
129             host->AddChild(header, 0);
130             // Initialize headerIndex_, itemStartIndex_
131             if (headerIndex_ == -1) {
132                 auto count = header->FrameCount();
133                 if (count > 0) {
134                     headerIndex_ = 0;
135                     itemStartIndex_ += count;
136                 }
137                 if (footerIndex_ >= 0) {
138                     footerIndex_ = footerIndex_ + count;
139                 }
140             }
141             host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
142         } else {
143             if (header != prevHeader) {
144                 host->ReplaceChild(prevHeader, header);
145                 host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
146             }
147         }
148         header_ = header;
149     }
150 
AddFooter(const RefPtr<NG::UINode> & footer)151     void AddFooter(const RefPtr<NG::UINode>& footer)
152     {
153         auto host = GetHost();
154         CHECK_NULL_VOID(host);
155         auto prevFooter = footer_.Upgrade();
156         auto prevHeader = header_.Upgrade();
157         if (!prevFooter) {
158             if (prevHeader) {
159                 host->AddChildAfter(footer, prevHeader);
160             } else {
161                 host->AddChild(footer, 0);
162             }
163             // Initialize itemStartIndex_, footerIndex_
164             if (footerIndex_ == -1) {
165                 int32_t count = footer->FrameCount();
166                 if (count > 0) {
167                     footerIndex_ = itemStartIndex_;
168                     itemStartIndex_ += count;
169                 }
170             }
171             host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
172         } else {
173             if (footer != prevFooter) {
174                 host->ReplaceChild(prevFooter, footer);
175                 host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
176             }
177         }
178         footer_ = footer;
179     }
180 
RemoveHeader()181     void RemoveHeader()
182     {
183         auto host = GetHost();
184         CHECK_NULL_VOID(host);
185         auto prevHeader = header_.Upgrade();
186         if (prevHeader && isHeaderComponentContentExist_) {
187             host->RemoveChild(prevHeader);
188             host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
189             header_ = nullptr;
190             headerIndex_ = -1;
191             itemStartIndex_ = 0;
192             isHeaderComponentContentExist_ = false;
193         }
194     }
195 
RemoveFooter()196     void RemoveFooter()
197     {
198         auto host = GetHost();
199         CHECK_NULL_VOID(host);
200         auto prevFooter = footer_.Upgrade();
201         if (prevFooter && isFooterComponentContentExist_) {
202             host->RemoveChild(prevFooter);
203             host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
204             footer_ = nullptr;
205             footerIndex_ = -1;
206             footerCount_ = 0;
207             isFooterComponentContentExist_ = false;
208         }
209     }
210 
IsHasHeader()211     bool IsHasHeader()
212     {
213         auto headerNode = DynamicCast<FrameNode>(header_.Upgrade());
214         return headerNode ? true : false;
215     }
216 
IsHasFooter()217     bool IsHasFooter()
218     {
219         auto footerGroup = DynamicCast<FrameNode>(footer_.Upgrade());
220         return footerGroup ? true : false;
221     }
222 
GetItemPosition()223     const ListItemGroupLayoutAlgorithm::PositionMap& GetItemPosition()
224     {
225         return itemPosition_;
226     }
227 
SetIndexInList(int32_t index)228     void SetIndexInList(int32_t index)
229     {
230         indexInList_ = index;
231     }
232 
SetHeaderComponentContentExist(bool isHeaderComponentContentExist)233     void SetHeaderComponentContentExist(bool isHeaderComponentContentExist)
234     {
235         isHeaderComponentContentExist_ = isHeaderComponentContentExist;
236     }
237 
SetFooterComponentContentExist(bool isFooterComponentContentExist)238     void SetFooterComponentContentExist(bool isFooterComponentContentExist)
239     {
240         isFooterComponentContentExist_ = isFooterComponentContentExist;
241     }
242 
GetIndexInList()243     int32_t GetIndexInList() const
244     {
245         return indexInList_;
246     }
247 
GetDisplayEndIndexInGroup()248     int32_t GetDisplayEndIndexInGroup() const
249     {
250         return itemDisplayEndIndex_;
251     }
252 
GetDisplayStartIndexInGroup()253     int32_t GetDisplayStartIndexInGroup() const
254     {
255         return itemDisplayStartIndex_;
256     }
257 
GetItemStartIndex()258     int32_t GetItemStartIndex() const
259     {
260         return itemStartIndex_;
261     }
262 
GetEndIndexInGroup()263     int32_t GetEndIndexInGroup() const
264     {
265         return (itemTotalCount_ - 1);
266     }
267 
GetTotalItemCount()268     int32_t GetTotalItemCount() const
269     {
270         return itemTotalCount_;
271     }
272 
IsDisplayStart()273     bool IsDisplayStart() const
274     {
275         return itemDisplayStartIndex_ == 0;
276     }
277 
IsDisplayEnd()278     int32_t IsDisplayEnd() const
279     {
280         return itemTotalCount_ == 0 || itemDisplayEndIndex_ == (itemTotalCount_ - 1);
281     }
282 
GetLanesInGroup()283     int32_t GetLanesInGroup() const
284     {
285         return lanes_;
286     }
287 
SetLanes(int32_t num)288     void SetLanes(int32_t num)
289     {
290         lanes_ = num;
291     }
292 
GetListItemGroupStyle()293     V2::ListItemGroupStyle GetListItemGroupStyle()
294     {
295         return listItemGroupStyle_;
296     }
297 
GetHeaderMainSize()298     float GetHeaderMainSize() const
299     {
300         return headerMainSize_;
301     }
302 
GetFooterMainSize()303     float GetFooterMainSize() const
304     {
305         return footerMainSize_;
306     }
307 
308     float GetEstimateOffset(float height, const std::pair<float, float>& targetPos,
309         float headerMainSize, float footerMainSize) const;
310     float GetEstimateHeight(float& averageHeight, float headerMainSize, float footerMainSize, float spaceWidth) const;
HasLayoutedItem()311     bool HasLayoutedItem() const
312     {
313         return layouted_ && (layoutedItemInfo_.has_value() || itemTotalCount_ == 0);
314     }
315 
SetItemPressed(bool isPressed,int32_t id)316     void SetItemPressed(bool isPressed, int32_t id)
317     {
318         if (isPressed) {
319             pressedItem_.emplace(id);
320         } else {
321             pressedItem_.erase(id);
322         }
323     }
324 
ResetLayoutedInfo()325     void ResetLayoutedInfo()
326     {
327         layouted_ = false;
328         layoutedItemInfo_.reset();
329         itemPosition_.clear();
330     }
331 
332     void SetListItemGroupStyle(V2::ListItemGroupStyle style);
333     RefPtr<ListChildrenMainSize> GetOrCreateListChildrenMainSize();
334     void SetListChildrenMainSize(float defaultSize, const std::vector<float>& mainSize);
335     void OnChildrenSizeChanged(std::tuple<int32_t, int32_t, int32_t> change, ListChangeFlag flag);
336     bool ListChildrenSizeExist();
337     RefPtr<FrameNode> GetListFrameNode() const;
338     VisibleContentInfo GetStartListItemIndex();
339     VisibleContentInfo GetEndListItemIndex();
340     void ResetChildrenSize();
341     bool IsInViewport(int32_t index) const;
342 
343     void ClearItemPosition();
344     void ClearCachedItemPosition();
345     void CalculateItemStartIndex();
346     bool NeedCacheForward(const LayoutWrapper* listWrapper) const;
347     CachedIndexInfo UpdateCachedIndex(bool outOfView, bool reCache, int32_t forwardCache, int32_t backwardCache);
348     int32_t UpdateCachedIndexForward(bool outOfView, bool show, int32_t cacheCount);
349     int32_t UpdateCachedIndexBackward(bool outOfView, bool show, int32_t cacheCount);
350     std::pair<int32_t, int32_t> UpdateCachedIndexOmni(int32_t forwardCache, int32_t backwardCache);
351     void UpdateActiveChildRange(bool forward, int32_t cacheCount, bool show);
352     void UpdateActiveChildRange(bool show);
353     void SyncItemsToCachedItemPosition();
354     bool IsVisible() const;
SetRecache(bool value)355     void SetRecache(bool value)
356     {
357         reCache_ = value;
358     }
359     void LayoutCache(const LayoutConstraintF& constraint, int64_t deadline, int32_t forwardCached,
360         int32_t backwardCached, ListMainSizeValues listSizeValues);
361 
GetHeader()362     RefPtr<UINode> GetHeader() const
363     {
364         return header_.Upgrade();
365     }
366 
GetFooter()367     RefPtr<UINode> GetFooter() const
368     {
369         return footer_.Upgrade();
370     }
371 
372     void OnColorModeChange(uint32_t colorMode) override;
373     void UpdateDefaultColor();
374 
ChildPreMeasureHelperEnabled()375     bool ChildPreMeasureHelperEnabled() override
376     {
377         return true;
378     }
PostponedTaskForIgnoreEnabled()379     bool PostponedTaskForIgnoreEnabled() override
380     {
381         return true;
382     }
383 
NeedCustomizeSafeAreaPadding()384     bool NeedCustomizeSafeAreaPadding() override
385     {
386         return true;
387     }
388 
ChildTentativelyLayouted()389     bool ChildTentativelyLayouted() override
390     {
391         return true;
392     }
393 
394 private:
395     bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override;
396     void OnAttachToFrameNode() override;
397     void OnAttachToFrameNodeMultiThread();
398     void OnAttachToMainTree() override;
399     void OnAttachToMainTreeMultiThread();
400     void SetListItemGroupDefaultAttributes(const RefPtr<FrameNode>& itemGroupNode);
401     void OnColorConfigurationUpdate() override;
402     void CheckListDirectionInCardStyle();
403     float GetPaddingAndMargin() const;
404     float GetListPaddingOffset(const RefPtr<FrameNode>& listNode) const;
405     bool FirstItemFullVisible(const RefPtr<FrameNode>& listNode) const;
406     bool CheckDataChangeOutOfStart(int32_t index, int32_t count, int32_t startIndex, int32_t endIndex);
407 
408     void HandleForwardStep(
409         const RefPtr<FrameNode>& curFrame, int32_t curIndexInGroup, int32_t& moveStep, int32_t& nextIndex);
410     void HandleBackwardStep(
411         const RefPtr<FrameNode>& curFrame, int32_t curIndexInGroup, int32_t& moveStep, int32_t& nextIndex);
412     bool HandleCrossAxisRightOrDownStep(
413         bool isVertical, int32_t curIndexInGroup, int32_t& moveStep, int32_t& nextIndex);
414     bool HandleCrossAxisLeftOrUpStep(bool isVertical, int32_t curIndexInGroup, int32_t& moveStep, int32_t& nextIndex);
415 
416     bool GetCurrentFocusIndices(
417         const RefPtr<FrameNode>& curFrame, const RefPtr<Pattern>& curPattern, int32_t& curIndexInGroup);
418     bool IsListVertical() const;
419     void AdjustFocusStepForRtl(FocusStep& step, bool isVertical);
420     bool DetermineSingleLaneStep(
421         FocusStep step, bool isVertical, int32_t curIndex, int32_t& moveStep, int32_t& nextIndex);
422     bool DetermineMultiLaneStep(FocusStep step, bool isVertical, const RefPtr<FrameNode>& curFrame,
423         int32_t curIndexInGroup, int32_t& moveStep, int32_t& nextIndex);
424     bool IsIndexInValidRange(int32_t index, int32_t maxIndex);
425     bool IsFocusMovementBlock(int32_t nextIndex, int32_t curIndex, int32_t maxIndex) const;
426     WeakPtr<FocusHub> FindNextValidFocus(int32_t moveStep, int32_t curIndexInGroup, int32_t curGroupIndexInList,
427         int32_t nextIndexInGroup, const WeakPtr<FocusHub>& currentFocusNode, FocusStep step);
428     void AdjustMountTreeSequence(int32_t footerCount);
429     void MappingPropertiesFromLayoutAlgorithm(const RefPtr<ListItemGroupLayoutAlgorithm>& layoutAlgorithm);
430     const ListItemGroupInfo* GetPosition(int32_t index) const;
431     bool NextPositionBlocksMove(
432         const ListItemGroupInfo* curPos, const ListItemGroupInfo* nextPos, bool isVertical) const;
433 
434     RefPtr<ShallowBuilder> shallowBuilder_;
435     RefPtr<ListPositionMap> posMap_;
436     RefPtr<ListChildrenMainSize> childrenSize_;
437     V2::ListItemGroupStyle listItemGroupStyle_ = V2::ListItemGroupStyle::NONE;
438 
439     int32_t indexInList_ = 0;
440 
441     WeakPtr<UINode> header_;
442     WeakPtr<UINode> footer_;
443     bool isHeaderComponentContentExist_ = false;
444     bool isFooterComponentContentExist_ = false;
445     int32_t itemStartIndex_ = 0;
446     int32_t headerIndex_ = -1;
447     int32_t footerIndex_ = -1;
448     int32_t footerCount_ = 0;
449     int32_t itemTotalCount_ = -1;
450     int32_t itemDisplayEndIndex_ = -1;
451     int32_t itemDisplayStartIndex_ = -1;
452     float_t headerMainSize_ = 0.0f;
453     float_t footerMainSize_ = 0.0f;
454 
455     std::optional<LayoutedItemInfo> layoutedItemInfo_;
456     std::set<int32_t> pressedItem_;
457     bool layouted_ = false;
458 
459     bool reCache_ = false;
460     int32_t backwardCachedIndex_ = INT_MAX;
461     int32_t forwardCachedIndex_ = -1;
462     ListItemGroupLayoutAlgorithm::PositionMap cachedItemPosition_;
463     float adjustRefPos_ = 0.0f;
464     float adjustTotalSize_ = 0.0f;
465 
466     ListItemGroupLayoutAlgorithm::PositionMap itemPosition_;
467     float spaceWidth_ = 0.0f;
468     Axis axis_ = Axis::VERTICAL;
469     int32_t lanes_ = 1;
470     float laneGutter_ = 0.0f;
471     float startHeaderPos_ = 0.0f;
472     float endFooterPos_ = 0.0f;
473     TextDirection layoutDirection_ = TextDirection::LTR;
474     float mainSize_ = 0.0f;
475     float listContentSize_ = 0.0f;
476     bool isStackFromEnd_ = false;
477     bool prevMeasureBreak_ = false;
478     ACE_DISALLOW_COPY_AND_MOVE(ListItemGroupPattern);
479 };
480 } // namespace OHOS::Ace::NG
481 
482 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_LIST_LIST_ITEM_PATTERN_H
483