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