1 /*
2  * Copyright (c) 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_SYNTAX_REPEAT_VIRTUAL_SCROLL_NODE_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_SYNTAX_REPEAT_VIRTUAL_SCROLL_NODE_H
18 
19 #include <cstdint>
20 #include <list>
21 #include <string>
22 #include <functional>
23 
24 #include "base/memory/referenced.h"
25 #include "base/utils/macros.h"
26 #include "core/components_ng/base/ui_node.h"
27 #include "core/components_ng/syntax/for_each_base_node.h"
28 #include "core/components_ng/syntax/repeat_virtual_scroll_caches.h"
29 
30 namespace OHOS::Ace::NG {
31 struct OffscreenItems {
32     int32_t from = -1;
33     int32_t to = -1;
34 };
35 
36 class ACE_EXPORT RepeatVirtualScrollNode : public ForEachBaseNode {
37     DECLARE_ACE_TYPE(RepeatVirtualScrollNode, ForEachBaseNode);
38 
39 public:
40     static RefPtr<RepeatVirtualScrollNode> GetOrCreateRepeatNode(int32_t nodeId, uint32_t totalCount,
41         const std::map<std::string, std::pair<bool, uint32_t>>& templateCachedCountMap,
42         const std::function<void(uint32_t)>& onCreateNode,
43         const std::function<void(const std::string&, uint32_t)>& onUpdateNode,
44         const std::function<std::list<std::string>(uint32_t, uint32_t)>& onGetKeys4Range,
45         const std::function<std::list<std::string>(uint32_t, uint32_t)>& onGetTypes4Range,
46         const std::function<void(int32_t, int32_t)>& onSetActiveRange);
47 
48     RepeatVirtualScrollNode(int32_t nodeId, int32_t totalCount,
49         const std::map<std::string, std::pair<bool, uint32_t>>& templateCacheCountMap,
50         const std::function<void(uint32_t)>& onCreateNode,
51         const std::function<void(const std::string&, uint32_t)>& onUpdateNode,
52         const std::function<std::list<std::string>(uint32_t, uint32_t)>& onGetKeys4Range,
53         const std::function<std::list<std::string>(uint32_t, uint32_t)>& onGetTypes4Range,
54         const std::function<void(int32_t, int32_t)>& onSetActiveRange);
55 
56     ~RepeatVirtualScrollNode() override = default;
57 
58     void UpdateTotalCount(uint32_t totalCount);
59 
60     // Number of children that Repeat can product
61     // returns TotalCount
62     int32_t FrameCount() const override;
63 
64     // called from TS upon Repeat rerender
65     void UpdateRenderState(bool visibleItemsChanged);
66 
67     /**
68      * GetChildren re-assembles children_ and cleanup the L1 cache
69      * active items remain in L1 cache and are added to RepeatVirtualScroll.children_
70      * inactive items are moved from L1 to L2 cache, not added to children_
71      * function returns children_
72      * function runs as part of idle task
73      */
74     const std::list<RefPtr<UINode>>& GetChildren(bool notDetach = false) const override;
75 
76     void OnRecycle() override;
77     void OnReuse() override;
78 
79     /**
80      * scenario: called by layout informs:
81      *   - start: the first visible index
82      *   - end: the last visible index
83      *   - cacheStart: number of items cached before start
84      *   - cacheEnd: number of items cached after end
85      *
86      * Total L1 cache includes items from start-cacheStart to end+cacheEnd,
87      * but the active items are only start...end.
88      *
89      * those items with index in range [ start ... end ] are marked active
90      * those out of range marked inactive.
91      *
92      * those items out of cached range are removed from L1
93      * requests idle task
94      */
95     void DoSetActiveChildRange(
96         int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd, bool showCache = false) override;
97 
98     /**
99      * those items with index in cachedItems are marked active
100      * those items with index in cachedItems are marked inactive
101      * baseIndex is repeat first node index
102      */
103     void DoSetActiveChildRange(
104         const std::set<int32_t>& activeItems, const std::set<int32_t>& cachedItems, int32_t baseIndex) override;
105 
106     // largely unknown when it is expected to be called
107     // meant to inform which items with index [ from .. to ] can be recycled / updated
108     void RecycleItems(int32_t from, int32_t to) override;
109 
110     // Called by parent generate frame child.
111     void SetNodeIndexOffset(int32_t start, int32_t count) override;
112 
113     /** Called by Layout to request ListItem and child subtree
114      for given index
115      either returns existing item for index from L1 or L2 cache, or gets a new item created
116      update of L2 cache item to new index)
117      result is in L1 cache if isCache is false, and L2 cache if isCache is true.
118 
119      meaning of parameters
120      needBuild: true - if found in cache, then return, if not in cache then return newly build
121                 false: - if found in cache, then return, if not found in cache then return nullptr
122      isCache: true indicates prebuild item (only used by List/Grid/Waterflow, this item should go to L2 cache,
123             do not add to the tree,
124             isCaxche==false this item is for display or near display area
125     addToRenderTree: true  - set it to active state, call SetActive
126     */
127     RefPtr<UINode> GetFrameChildByIndex(
128         uint32_t index, bool needBuild, bool isCache = false, bool addToRenderTree = false) override;
129 
IsAtomicNode()130     bool IsAtomicNode() const override
131     {
132         return false;
133     }
134 
135     // used for drag move operation.
136     void SetOnMove(std::function<void(int32_t, int32_t)>&& onMove);
137     void MoveData(int32_t from, int32_t to) override;
138     RefPtr<FrameNode> GetFrameNode(int32_t index) override;
139     int32_t GetFrameNodeIndex(const RefPtr<FrameNode>& node, bool isExpanded = true) override;
140     void InitDragManager(const RefPtr<UINode>& childNode);
141     void InitAllChildrenDragManager(bool init);
142 
143     void OnConfigurationUpdate(const ConfigurationChange& configurationChange) override;
144 
145     void SetJSViewActive(bool active = true, bool isLazyForEachNode = false) override
146     {
147         const auto& children = caches_.GetAllNodes();
148         for (const auto& [key, child] : children) {
149             child.item->SetJSViewActive(active);
150         }
151         isActive_ = active;
152     }
PaintDebugBoundaryTreeAll(bool flag)153     void PaintDebugBoundaryTreeAll(bool flag) override
154     {
155         const auto& children = caches_.GetAllNodes();
156         for (const auto& [key, child] : children) {
157             child.item->PaintDebugBoundaryTreeAll(flag);
158         }
159     }
SetIsLoop(bool isLoop)160     void SetIsLoop(bool isLoop)
161     {
162         isLoop_ = isLoop;
163     }
164 protected:
165     void UpdateChildrenFreezeState(bool isFreeze) override;
166 private:
167     void PostIdleTask();
168 
169     // try to find entry for given index in L1 or L2 cache
GetFromCaches(uint32_t forIndex)170     RefPtr<UINode> GetFromCaches(uint32_t forIndex)
171     {
172         return caches_.GetCachedNode4Index(forIndex);
173     }
174 
175     // get farthest (from L1 indexes) index in L2 cache or -1
176     int32_t GetFarthestL2CacheIndex();
177 
178     // drop UINode with given key from L1 but keep in L2
179     // detach from tree and request tree sync
180     void DropFromL1(const std::string& key);
181 
182     // check whether UINode (index) is in the L1 cache range
183     bool CheckNode4IndexInL1(int32_t index, int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd,
184         RefPtr<FrameNode>& frameNode);
185 
186     // process params sent by parent
187     void CheckActiveRange(int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd);
188 
189     // RepeatVirtualScrollNode is not instance of FrameNode
190     // needs to propagate active state to all items inside
191     bool isActive_ = true;
192 
193     // size of data source when all data items loaded
194     uint32_t totalCount_ = 0;
195 
196     // loop property of the parent container
197     bool isLoop_ = false;
198 
199     // caches:
200     mutable RepeatVirtualScrollCaches caches_;
201 
202     // get active child range
203     std::function<void(int32_t, int32_t)> onSetActiveRange_;
204 
205     // used by one of the unknown functions
206     std::list<std::string> ids_;
207 
208     // re-assembled by GetChildren called from idle task
209     mutable std::list<RefPtr<UINode>> children_;
210 
211     // true in the time from requesting idle / predict task until exec predict tsk.
212     bool postUpdateTaskHasBeenScheduled_;
213 
214     // STATE_MGMT_NOTE: What are these?
215     OffscreenItems offscreenItems_;
216     int32_t startIndex_ = 0;
217 
218     ACE_DISALLOW_COPY_AND_MOVE(RepeatVirtualScrollNode);
219 };
220 } // namespace OHOS::Ace::NG
221 
222 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_SYNTAX_REPEAT_VIRTUAL_SCROLL_NODE_H
223